HTML メールの本文
', '', null); assertError(main, 'At least one To Email Address is required.'); }); /** * To の個数が多すぎる(文字型データ項目) */ test('Too many To Email Addresses - set by STRING', () => { const toStr = createListString('to', MAX_RECIPIENT_NUM + 1); prepareConfigs('from@example.com', '', toStr, null, null, '件名', 'HTML メールの本文
', '', null); assertError(main, `The maximum number of recipients (To + Cc + Bcc) is ${MAX_RECIPIENT_NUM}.`); }); /** * To, Cc, Bcc の合計個数が多すぎる(文字型データ項目) */ test('Too many recipients - set by STRING', () => { const bccStr = createListString('bcc', MAX_RECIPIENT_NUM - 1); prepareConfigs('from@example.com', '', 'to@example.com', 'cc@example.com', bccStr, '件名', 'HTML メールの本文
', '', null); assertError(main, `The maximum number of recipients (To + Cc + Bcc) is ${MAX_RECIPIENT_NUM}.`); }); /** * To, Cc の指定が重複(文字型データ項目) */ test('Same email address between To and Cc - set by STRING', () => { prepareConfigs('from@example.com', '', 'test@example.com\nto@example.com', 'test@example.com', null, '件名', 'HTML メールの本文
', '', null); assertError(main, 'Each email address must be unique between To, Cc, and Bcc.'); }); /** * Cc, Bcc の指定が重複(文字型データ項目) */ test('Same email address between Cc and Bcc - set by STRING', () => { prepareConfigs('from@example.com', '', 'to@example.com', 'cc@example.com\ntest@example.com', 'test@example.com', '件名', 'HTML メールの本文
', '', null); assertError(main, 'Each email address must be unique between To, Cc, and Bcc.'); }); /** * To, Bcc の指定が重複(文字型データ項目) */ test('Same email address between To and Bcc - set by STRING', () => { prepareConfigs('from@example.com', '', 'to@example.com\ntest@example.com', null, 'test@example.com', '件名', 'HTML メールの本文
', '', null); assertError(main, 'Each email address must be unique between To, Cc, and Bcc.'); }); /** * 件名が空 */ test('Subject is blank', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '', 'HTML メールの本文
', '', null); assertError(main, 'Subject is blank.'); }); /** * HTML 本文とプレーンテキスト本文がともに空 */ test('Content is Blank', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', '', '', null); assertError(main, 'HTML Content and Plain Content are blank. At least one of them is required.'); }); /** * インライン画像に画像ファイル以外を指定 */ test('Content-Type of an inline image does not start with image/', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', 'HTML メールの本文
', '', null); const file = engine.createQfile('画像でないファイル', 'text/plain', 'aaa'); setDataItem('InlineImages', 10, 'FILE', [file]); assertError(main, '画像でないファイル is not an image.'); }); /** * カテゴリの個数が多すぎる(文字型データ項目) */ test('Too many Categories - set by STRING', () => { const categoriesStr = createListString('category', MAX_CATEGORY_NUM + 1); prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', 'HTML メールの本文
', '', categoriesStr); assertError(main, `The maximum number of Categories is ${MAX_CATEGORY_NUM}.`); }); /** * カテゴリに ASCII 文字以外を含む(文字型データ項目) */ test('Categories include invalid characters - set by STRING', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', 'HTML メールの本文
', '', 'categoryてすと'); assertError(main, 'Categories cannot include non-ascii characters.'); }); /** * 長すぎるカテゴリを含む(文字型データ項目) */ test('Category is loo long - set by STRING', () => { const categoriesStr = createListString('category', MAX_CATEGORY_NUM - 1) + createString(MAX_CATEGORY_LENGTH + 1); prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', 'HTML メールの本文
', '', categoriesStr); assertError(main, `Each category must be within ${MAX_CATEGORY_LENGTH} characters.`); }); /** * カテゴリの指定が重複(文字型データ項目) */ test('Same category is set multiple times - set by STRING', () => { const categoriesStr = createListString('category', MAX_CATEGORY_NUM - 1) + 'category1'; prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', 'HTML メールの本文
', '', categoriesStr); assertError(main, 'The same category is set multiple times.'); }); /** * メールを送信する API リクエストのテスト * @param {Object} request * @param request.url * @param request.method * @param request.contentType * @param request.body * @param fromEmail * @param fromName * @param replyToEmail * @param replyToName * @param sendAt * @param trackOpen * @param to * @param cc * @param bcc * @param subject * @param htmlContent * @param plainContent * @param categories */ const assertRequest = ({ url, method, contentType, body }, fromEmail, fromName, replyToEmail, replyToName, sendAt, trackOpen, to, cc, bcc, subject, htmlContent, plainContent, categories) => { expect(url).toEqual('https://api.sendgrid.com/v3/mail/send'); expect(method).toEqual('POST'); expect(contentType).toEqual('application/json'); const bodyObj = JSON.parse(body); expect(bodyObj.from.email).toEqual(fromEmail); expect(bodyObj.from.name).toEqual(fromName); if (replyToEmail !== undefined) { expect(bodyObj.reply_to.email).toEqual(replyToEmail); expect(bodyObj.reply_to.name).toEqual(replyToName); } expect(bodyObj.send_at).toEqual(sendAt); expect(bodyObj.tracking_settings.open_tracking.enable).toEqual(trackOpen); expect(bodyObj.personalizations.length).toEqual(1); expect(bodyObj.personalizations[0].to.length).toEqual(to.length); to.forEach(({ email, name }, i) => { expect(bodyObj.personalizations[0].to[i].email).toEqual(email); expect(bodyObj.personalizations[0].to[i].name).toEqual(name); }); if (cc !== undefined) { expect(bodyObj.personalizations[0].cc.length).toEqual(cc.length); cc.forEach(({ email, name }, i) => { expect(bodyObj.personalizations[0].cc[i].email).toEqual(email); expect(bodyObj.personalizations[0].cc[i].name).toEqual(name); }); } if (bcc !== undefined) { expect(bodyObj.personalizations[0].bcc.length).toEqual(bcc.length); bcc.forEach(({ email, name }, i) => { expect(bodyObj.personalizations[0].bcc[i].email).toEqual(email); expect(bodyObj.personalizations[0].bcc[i].name).toEqual(name); }); } expect(bodyObj.subject).toEqual(subject); let i = 0; if (plainContent !== undefined) { expect(bodyObj.content[i].type).toEqual('text/plain'); expect(bodyObj.content[i].value).toEqual(plainContent); i++; } if (htmlContent !== undefined) { expect(bodyObj.content[i].type).toEqual('text/html'); expect(bodyObj.content[i].value).toEqual(htmlContent); } expect(bodyObj.categories).toEqual(categories); }; /** * メールを送信する API リクエストでエラー */ test('Fail to send mail', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', 'HTML メールの本文
', '', null); httpClient.setRequestHandler((request) => { assertRequest(request, 'from@example.com', undefined, undefined, undefined, undefined, false, [{email: 'to1@example.com'}], undefined, undefined, '件名', 'HTML メールの本文
', undefined, undefined); return httpClient.createHttpResponse(400, 'application/json', '{}'); }); assertError(main, 'Failed to send mail. status: 400'); }); /** * 成功 * HTML 本文のみ指定 * Reply-To 指定なし * 送信日時指定なし * メール開封検知なし * カテゴリ指定なし */ test('Succeed - With HTML content, no schduled datetime, no categories', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名 1', 'HTML メールの本文
', '', null); httpClient.setRequestHandler((request) => { assertRequest(request, 'from@example.com', undefined, undefined, undefined, undefined, false, [{email: 'to1@example.com'}], undefined, undefined, '件名 1', 'HTML メールの本文
', undefined, undefined); return httpClient.createHttpResponse(202, 'application/json', ''); }); main(); }); /** * 成功 * HTML 本文、プレーンテキスト本文の両方を指定 * Reply-To のメールアドレスのみ指定 * 送信日時指定なし * メール開封検知あり * カテゴリ指定あり */ test('Succeed - With both HTML content and plain text content, with reply-to email, no schduled datetime, with categories', () => { prepareConfigs('from@example.com', '', 'to1@example.com\nto2@example.com', null, null, '件名 2', 'HTML メールの本文
', 'プレーンテキストメールの本文', 'category1\ncategory2'); configs.put('conf_ReplyTo', 'replyto@example.com'); configs.putObject('conf_TrackOpen', true); httpClient.setRequestHandler((request) => { assertRequest(request, 'from@example.com', undefined, 'replyto@example.com', undefined, undefined, true, [{email: 'to1@example.com'}, {email: 'to2@example.com'}], undefined, undefined, '件名 2', 'HTML メールの本文
', 'プレーンテキストメールの本文', ['category1', 'category2']); return httpClient.createHttpResponse(202, 'application/json', ''); }); main(); }); /** * 送信日時を設定 * @param timestamp */ const setSendAt = (timestamp) => { const def = engine.createDataDefinition('送信日時', 10, 'q_sendAt', 'DATETIME'); if (timestamp !== null) { engine.setData(def, timestamp); } configs.putObject('conf_SendAt', def); } /** * 送信日時が選択されているのに、値が空 */ test('Scheduled Datetime is null', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', 'HTML メールの本文
', '', null); setSendAt(null); assertError(main, 'Scheduled Datetime is selected but its data is null.'); }); /** * 送信日時が過去 */ test('Scheduled Datetime has passed', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', 'HTML メールの本文
', '', null); const timestamp = new com.questetra.bpms.util.AddableTimestamp().addMinutes(-1); setSendAt(timestamp); assertError(main, 'Scheduled Datetime must be future.'); }); /** * 送信日時が 72 時間以上先 */ test('Scheduled Datetime is too late', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', 'HTML メールの本文
', '', null); const timestamp = new com.questetra.bpms.util.AddableTimestamp().addHours(MAX_SCHEDULABLE_HOURS + 1); setSendAt(timestamp); assertError(main, `Scheduled Datetime must be within ${MAX_SCHEDULABLE_HOURS} hours.`); }); /** * 成功 * プレーンテキスト本文のみ指定 * From 表示名あり * Reply-To 表示名あり * 送信日時指定あり */ test('Succeed - With plain text content, with from display name, with reply-to email and its display name, with schduled datetime', () => { const to = createListString('to', 10); const cc = createListString('cc', 20); const bcc = createListString('bcc', MAX_RECIPIENT_NUM - 30); const toList = to.split('\n').filter((email) => email !== '').map(email => ({ email })); const ccList = cc.split('\n').filter((email) => email !== '').map(email => ({ email })); const bccList = bcc.split('\n').filter((email) => email !== '').map(email => ({ email })); prepareConfigs('from@example.com', 'From 表示名', to, cc, bcc, '件名 3', '', 'プレーンテキストメールの本文', null); configs.put('conf_ReplyTo', 'replyto@example.com'); configs.put('conf_ReplyToName', 'Reply-To 表示名'); const timestamp = new com.questetra.bpms.util.AddableTimestamp().addMinutes(30); setSendAt(timestamp); httpClient.setRequestHandler((request) => { assertRequest(request, 'from@example.com', 'From 表示名', 'replyto@example.com', 'Reply-To 表示名', Math.floor(timestamp.getTime() / 1000), false, toList, ccList, bccList, '件名 3', undefined, 'プレーンテキストメールの本文', undefined); return httpClient.createHttpResponse(202, 'application/json', ''); }); main(); }); /** * 選択型データ設定用のオブジェクトを作成 * @param prefix * @param num * @return selects */ const prepareSelects = (prefix, num) => { const selects = new java.util.ArrayList(); for (let i = 0; i < num; i++) { const item = engine.createItem(`${prefix}${i + 1}`, `${prefix}${i + 1} のラベル`); selects.add(item); } return selects; }; /** * To, Cc, Bcc の合計個数が多すぎる(選択型データ項目) */ test('Too many recipients - set by SELECT', () => { prepareConfigs('from@example.com', '', null, null, null, '件名', 'HTML メールの本文
', '', null); setDataItem('To', 21, 'SELECT_CHECKBOX', prepareSelects('to_', 1)); setDataItem('Cc', 22, 'SELECT_CHECKBOX', prepareSelects('cc_', MAX_RECIPIENT_NUM)); assertError(main, `The maximum number of recipients (To + Cc + Bcc) is ${MAX_RECIPIENT_NUM}.`); }); /** * カテゴリの個数が多すぎる(選択型データ項目) */ test('Too many Categories - set by SELECT', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', 'HTML メールの本文
', '', null); setDataItem('Categories', 21, 'SELECT_CHECKBOX', prepareSelects('category_', MAX_CATEGORY_NUM + 1)); assertError(main, `The maximum number of Categories is ${MAX_CATEGORY_NUM}.`); }); /** * カテゴリに ASCII 文字以外を含む(選択型データ項目) */ test('Categories include invalid characters - set by SELECT', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', 'HTML メールの本文
', '', null); const categories = prepareSelects('category_', 3); const invalidCategory = 'catえgory'; categories.set(1, engine.createItem(invalidCategory, `${invalidCategory} のラベル`)); setDataItem('Categories', 21, 'SELECT_CHECKBOX', categories); assertError(main, 'Categories cannot include non-ascii characters.'); }); /** * 長すぎるカテゴリを含む(選択型データ項目) */ test('Category is loo long - set by SELECT', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名', 'HTML メールの本文
', '', null); const categories = prepareSelects('category_', 3); const longCategory = createString(MAX_CATEGORY_LENGTH + 1); categories.set(1, engine.createItem(longCategory, `${longCategory} のラベル`)); setDataItem('Categories', 21, 'SELECT_CHECKBOX', categories); assertError(main, `Each category must be within ${MAX_CATEGORY_LENGTH} characters.`); }); /** * 成功 * データ項目で指定できるものは、すべて選択型データ項目で指定 * カテゴリ指定なし */ test('Succeed - Configured by SELECT, no categories', () => { prepareConfigs('from1@example.com', '', null, null, null, '件名', 'HTML メールの本文
', '', 'dummy'); setDataItem('To', 22, 'SELECT_CHECKBOX', prepareSelects('to', 2)); setDataItem('Cc', 23, 'SELECT_CHECKBOX', prepareSelects('cc', 3)); setDataItem('Bcc', 24, 'SELECT_CHECKBOX', prepareSelects('bcc', 1)); setDataItem('Categories', 26, 'SELECT_CHECKBOX', new java.util.ArrayList()); const toList = [ {email: 'to1', name: 'to1 のラベル'}, {email: 'to2', name: 'to2 のラベル'} ]; const ccList = [ {email: 'cc1', name: 'cc1 のラベル'}, {email: 'cc2', name: 'cc2 のラベル'}, {email: 'cc3', name: 'cc3 のラベル'} ]; const bccList = [ {email: 'bcc1', name: 'bcc1 のラベル'} ]; httpClient.setRequestHandler((request) => { assertRequest(request, 'from1@example.com', undefined, undefined, undefined, undefined, false, toList, ccList, bccList, '件名', 'HTML メールの本文
', undefined, undefined); return httpClient.createHttpResponse(202, 'application/json', ''); }); main(); }); /** * 成功 * データ項目で指定できるものは、すべて選択型データ項目で指定 * カテゴリ指定あり */ test('Succeed - Configured by SELECT, with categories', () => { prepareConfigs('from1@example.com', '', null, null, null, '件名', 'HTML メールの本文
', '', 'dummy'); setDataItem('To', 22, 'SELECT_CHECKBOX', prepareSelects('to', 1)); setDataItem('Cc', 23, 'SELECT_CHECKBOX', prepareSelects('cc', 2)); setDataItem('Bcc', 24, 'SELECT_CHECKBOX', new java.util.ArrayList()); setDataItem('Categories', 26, 'SELECT_CHECKBOX', prepareSelects('category', 2)); const toList = [ {email: 'to1', name: 'to1 のラベル'} ]; const ccList = [ {email: 'cc1', name: 'cc1 のラベル'}, {email: 'cc2', name: 'cc2 のラベル'} ]; httpClient.setRequestHandler((request) => { assertRequest(request, 'from1@example.com', undefined, undefined, undefined, undefined, false, toList, ccList, undefined, '件名', 'HTML メールの本文
', undefined, ['category1', 'category2']); return httpClient.createHttpResponse(202, 'application/json', ''); }); main(); }); /** * API リクエストの body に添付ファイルが含まれることをテスト * @param requestBody * @param index * @param fileName * @param contentType * @param disposition * @param contentId */ const assertAttachment = (requestBody, index, fileName, contentType, disposition, contentId) => { const attachment = JSON.parse(requestBody).attachments[index]; // content のテストは省略 expect(attachment.filename).toEqual(fileName); expect(attachment.type).toEqual(contentType); expect(attachment.disposition).toEqual(disposition); expect(attachment.content_id).toEqual(contentId); }; /** * 成功 * インライン画像、添付ファイルを指定 */ test('Succeed - With inline images and attachments', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名 1', 'HTML メールの本文
', '', null); // インライン画像を指定 const inline1 = engine.createQfile('インライン画像1.png', 'image/png', 'aaa'); const inline2 = engine.createQfile('インライン画像2.jpg', 'image/jpeg', 'bbb'); const inline3 = engine.createQfile('インライン画像3.gif', 'image/gif', 'ccc'); setDataItem('InlineImages', 10, 'FILE', [inline1, inline2, inline3]); // 添付ファイルを指定 const attachment1 = engine.createQfile('添付ファイル1.txt', 'text/plain', 'ddd'); const attachment2 = engine.createQfile('添付ファイル2.jpg', 'image/jpeg', 'eee'); setDataItem('Attachments', 11, 'FILE', [attachment1, attachment2]); httpClient.setRequestHandler((request) => { assertRequest(request, 'from@example.com', undefined, undefined, undefined, undefined, false, [{email: 'to1@example.com'}], undefined, undefined, '件名 1', 'HTML メールの本文
', undefined, undefined); assertAttachment(request.body, 0, 'インライン画像1.png', 'image/png', 'inline', '0'); assertAttachment(request.body, 1, 'インライン画像2.jpg', 'image/jpeg', 'inline', '1'); assertAttachment(request.body, 2, 'インライン画像3.gif', 'image/gif', 'inline', '2'); assertAttachment(request.body, 3, '添付ファイル1.txt', 'text/plain; charset=UTF-8', 'attachment', undefined); assertAttachment(request.body, 4, '添付ファイル2.jpg', 'image/jpeg', 'attachment', undefined); return httpClient.createHttpResponse(202, 'application/json', ''); }); main(); }); /** * 成功 * 添付ファイルのみ指定。インライン画像はデータ項目を選択し、ファイル未添付 */ test('Succeed - With attachments, with no inline images', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名 1', 'HTML メールの本文
', '', null); // インライン画像はデータ項目を選択し、ファイル未添付 setDataItem('InlineImages', 10, 'FILE', null); // 添付ファイルを指定 const attachment1 = engine.createQfile('添付ファイル1.txt', 'text/plain', 'ddd'); const attachment2 = engine.createQfile('添付ファイル2.jpg', 'image/jpeg', 'eee'); setDataItem('Attachments', 11, 'FILE', [attachment1, attachment2]); httpClient.setRequestHandler((request) => { assertRequest(request, 'from@example.com', undefined, undefined, undefined, undefined, false, [{email: 'to1@example.com'}], undefined, undefined, '件名 1', 'HTML メールの本文
', undefined, undefined); assertAttachment(request.body, 0, '添付ファイル1.txt', 'text/plain; charset=UTF-8', 'attachment', undefined); assertAttachment(request.body, 1, '添付ファイル2.jpg', 'image/jpeg', 'attachment', undefined); return httpClient.createHttpResponse(202, 'application/json', ''); }); main(); }); /** * 成功 * 添付ファイルのみ指定。インライン画像はデータ項目の指定なし */ test('Succeed - With attachments, with inline images not selected', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名 1', 'HTML メールの本文
', '', null); // 添付ファイルを指定 const attachment1 = engine.createQfile('添付ファイル1.txt', 'text/plain', 'ddd'); const attachment2 = engine.createQfile('添付ファイル2.jpg', 'image/jpeg', 'eee'); setDataItem('Attachments', 11, 'FILE', [attachment1, attachment2]); httpClient.setRequestHandler((request) => { assertRequest(request, 'from@example.com', undefined, undefined, undefined, undefined, false, [{email: 'to1@example.com'}], undefined, undefined, '件名 1', 'HTML メールの本文
', undefined, undefined); assertAttachment(request.body, 0, '添付ファイル1.txt', 'text/plain; charset=UTF-8', 'attachment', undefined); assertAttachment(request.body, 1, '添付ファイル2.jpg', 'image/jpeg', 'attachment', undefined); return httpClient.createHttpResponse(202, 'application/json', ''); }); main(); }); /** * 成功 * インライン画像のみ指定。添付ファイルはデータ項目を選択し、ファイル未添付 */ test('Succeed - With inline images, with no attachments', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名 1', 'HTML メールの本文
', '', null); // インライン画像を指定 const inline1 = engine.createQfile('インライン画像1.png', 'image/png', 'aaa'); const inline2 = engine.createQfile('インライン画像2.jpg', 'image/jpeg', 'bbb'); const inline3 = engine.createQfile('インライン画像3.gif', 'image/gif', 'ccc'); setDataItem('InlineImages', 10, 'FILE', [inline1, inline2, inline3]); // 添付ファイルはデータ項目を指定し、ファイル未添付 setDataItem('Attachments', 11, 'FILE', null); httpClient.setRequestHandler((request) => { assertRequest(request, 'from@example.com', undefined, undefined, undefined, undefined, false, [{email: 'to1@example.com'}], undefined, undefined, '件名 1', 'HTML メールの本文
', undefined, undefined); assertAttachment(request.body, 0, 'インライン画像1.png', 'image/png', 'inline', '0'); assertAttachment(request.body, 1, 'インライン画像2.jpg', 'image/jpeg', 'inline', '1'); assertAttachment(request.body, 2, 'インライン画像3.gif', 'image/gif', 'inline', '2'); return httpClient.createHttpResponse(202, 'application/json', ''); }); main(); }); /** * 成功 * インライン画像のみ指定。添付ファイルはデータ項目の指定なし */ test('Succeed - With inline images, with attachments not selected', () => { prepareConfigs('from@example.com', '', 'to1@example.com', null, null, '件名 1', 'HTML メールの本文
', '', null); // インライン画像を指定 const inline1 = engine.createQfile('インライン画像1.png', 'image/png', 'aaa'); const inline2 = engine.createQfile('インライン画像2.jpg', 'image/jpeg', 'bbb'); const inline3 = engine.createQfile('インライン画像3.gif', 'image/gif', 'ccc'); setDataItem('InlineImages', 10, 'FILE', [inline1, inline2, inline3]); httpClient.setRequestHandler((request) => { assertRequest(request, 'from@example.com', undefined, undefined, undefined, undefined, false, [{email: 'to1@example.com'}], undefined, undefined, '件名 1', 'HTML メールの本文
', undefined, undefined); assertAttachment(request.body, 0, 'インライン画像1.png', 'image/png', 'inline', '0'); assertAttachment(request.body, 1, 'インライン画像2.jpg', 'image/jpeg', 'inline', '1'); assertAttachment(request.body, 2, 'インライン画像3.gif', 'image/gif', 'inline', '2'); return httpClient.createHttpResponse(202, 'application/json', ''); }); main(); }); ]]>