3 2 2023-08-25 (C) Questetra, Inc. (MIT License) This item sends bulk email to the contacts in the specified lists and/or segments on SendGrid. この工程は、SendGrid のリストやセグメントに含まれる宛先に、メールを一斉送信します。 https://support.questetra.com/bpmn-icons/service-task-sendgrid-email-send-bulk/ https://support.questetra.com/ja/bpmn-icons/service-task-sendgrid-email-send-bulk/ iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADBUlEQVRYR8WXS08TURTH/5cWBeXZ ipHFjBh3JIYSdKELYePGZCYS4jMxtiauwU+gJm40JpYPYKhxodEoj+4R4lYrjQsXimKrUhKRNxNC 22vuTMcZ5s50psLgbCY5c++c3zn33PMg+M8PqUh/MnMOFN0gJAKgCQB7s2cKwCIoZe8JyOKo1/+6 AwwvNCG42g9KB0AIU+r+ULoIQuLI1w2it3mx3IbyAGPfo0DxoWfFVk0qCGKQxBEnCGeAZDYOoN/d XA8rKI1DFm/arbQHSGYSALnm4dfel1CagCzGrBt4ABfL+w7V4lhDNae4LkiwmqecPKsU8Ci7pssH IQkD5kVbAdiZEzpUzqzJUy04HdrLLfm4mse9z8uc/OzBWlxMzZvktNccEwYAi/bAyle3gHMCSC1t ouvNHAfwpDOEq+9/G3IWmIX6I/rtMACS2dsAbrkd6rYBNAV3IAlMHwyAsQy7u427AsC8IIvNBgDL cCDDbsrZ9x3yAAAtFjQP2ET+DXE/zrTUcEztddVorani5OO/NvBNySNICIIECBCCKgJMr+Vxf3rF zjb1RmgAY9kJEHSbVz3vCuN8ay238ct6AUfHZzn565Mt6Anzt2Mkp6D3rfkWlLZSTEIWenQPzAA4 7AfAq5yCPjsAVsAkoVMH4DLITnngxayCC+9sPMCslQTiO8Czn+u4nDLlAbObTQC+HcHTH+u4Yk5E BkAakhBxDMKXx8OINOzhgq1IKeY2ipz8UmoeoycOcPLhnIK7n/gUDUsQcqV3qCOEWJp3XaV5oExu MV1Dm0TkP4A5Eam5YGsq9hWA0iXIotreORYjXwFsi5FWjmf0guQbALO+UN/Gl2P1GIyG5EF7I8LV AS6G2vYFwLof6/NheRPX0wse6plTQ6Jv3clmlMf52wfon3avKQV9DEmMWpl2py03BZ13ALVPUEex hJdOyfbwWcARRP9tMNH/qI1mA6XRzLVlU7epitXRLL690cxqlpYxe0ARAVGH047SkjQo2Bg2BdCJ chZXdgQeLtV2l/wBk2V1MIOcaTsAAAAASUVORK5CYII= { // 認証設定を準備 const auth = httpClient.createAuthSettingToken('SendGrid API Key', 'sendgrid-1234567'); configs.putObject('conf_Auth', auth); setDataItem('Categories', 1, 'STRING_TEXTAREA', categories); configs.put('conf_SenderId', senderId); setDataItem('ListIds', 2, 'STRING_TEXTAREA', listIds); setDataItem('SegmentIds', 3, 'STRING_TEXTAREA', segmentIds); setDataItem('UnsubscribeGroupId', 4, 'STRING_TEXTFIELD', unsubscribeGroupId); setDataItem('DesignId', 5, 'STRING_TEXTFIELD', designId); // ID を保存するデータ項目を作成し、設定 const idDef = setDataItem('SingleSendId', 11, 'STRING_TEXTFIELD', '事前文字列'); // URL を保存するデータ項目を作成し、設定 const urlDef = setDataItem('SingleSendUrl', 12, 'STRING_TEXTFIELD', '事前文字列'); return {idDef, urlDef}; }; /** * データ項目を作成し、config にセットする * @param name config 名の conf_ 以降 * @param index * @param type * @param value * @param dataDef */ const setDataItem = (name, index, type, value) => { const dataDef = engine.createDataDefinition(name, index, `q_${name}`, type); engine.setData(dataDef, value); configs.putObject(`conf_${name}`, dataDef); return dataDef; }; /** * 異常系のテスト * @param func * @param errorMsg */ const assertError = (func, errorMsg) => { try { func(); fail(); } catch (e) { expect(e.toString()).toEqual(errorMsg); } }; /** * 指定個数のデータを改行区切りにした文字列を生成する * @param num * @return string */ const createListString = (num) => { let string = ''; for (let i = 0; i < num; i++) { string += `item${i}\n`; } return string; }; /** * 指定の長さの文字列を作成 * @param length * @return string */ const createString = (length) => { const sourceStr = 'abcdefghijklmnopqrstuvwxyz'; const string = sourceStr.repeat(Math.floor(length / sourceStr.length)) + sourceStr.slice(0, length % sourceStr.length); return string; } /** * カテゴリの個数が多すぎる(文字型データ項目) */ test('Too many Categories - set by STRING', () => { const categoriesStr = createListString(MAX_CATEGORY_NUM + 1); prepareConfigs(categoriesStr, '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'design1'); assertError(main, `The maximum number of Categories is ${MAX_CATEGORY_NUM}.`); }); /** * カテゴリに ASCII 文字以外を含む(文字型データ項目) */ test('Categories include invalid characters - set by STRING', () => { prepareConfigs('categoryあ', '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'design1'); assertError(main, 'Categories cannot include non-ascii characters.'); }); /** * 長すぎるカテゴリを含む(文字型データ項目) */ test('Category is loo long - set by STRING', () => { const categoriesStr = createListString(MAX_CATEGORY_NUM - 1) + createString(MAX_CATEGORY_LENGTH + 1); prepareConfigs(categoriesStr, '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'design1'); assertError(main, `Each category must be within ${MAX_CATEGORY_LENGTH} characters.`); }); /** * カテゴリの指定が重複(文字型データ項目) */ test('Same category is set multiple times - set by STRING', () => { const categoriesStr = createListString(MAX_CATEGORY_NUM - 1) + 'item1'; prepareConfigs(categoriesStr, '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'design1'); assertError(main, 'The same category is set multiple times.'); }); /** * 送信者 ID が空 */ test('Sender ID is blank', () => { prepareConfigs(null, '', 'list1\nlist2', 'segment1\nsegment2', '123', 'design1'); assertError(main, 'Sender ID is blank.'); }); /** * 送信者 ID が整数でない */ test('Sender ID is not integer', () => { prepareConfigs(null, 'invalidId', 'list1\nlist2', 'segment1\nsegment2', '123', 'design1'); assertError(main, 'Sender ID must be integer.'); }); /** * 配信停止グループ ID が空(文字型データ項目) */ test('Unsubscribe Group ID is blank - set by STRING', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', null, 'design1'); assertError(main, 'Unsubscribe Group ID is blank.'); }); /** * 配信停止グループ ID が整数でない(文字型データ項目) */ test('Unsubscribe Group ID is not integer - set by STRING', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', 'invalidId', 'design1'); assertError(main, 'Unsubscribe Group ID must be integer.'); }); /** * リスト ID とセグメント ID がどちらも空(文字型データ項目) */ test('No List IDs or Segment IDs - set by STRING', () => { prepareConfigs(null, '123', null, null, '456', 'design1'); assertError(main, 'No List IDs or Segment IDs.'); }); /** * リスト ID の個数が多すぎる(文字型データ項目) */ test('Too many List IDs - set by STRING', () => { const listIdsStr = createListString(MAX_LIST_ID_NUM + 1); prepareConfigs(null, '123', listIdsStr, null, '456', 'design1'); assertError(main, `The maximum number of List IDs is ${MAX_LIST_ID_NUM}.`); }); /** * セグメント ID の個数が多すぎる(文字型データ項目) */ test('Too many Segment IDs - set by STRING', () => { const segmentIdsStr = createListString(MAX_SEGMENT_ID_NUM + 1); prepareConfigs(null, '123', null, segmentIdsStr, '456', 'design1'); assertError(main, `The maximum number of Segment IDs is ${MAX_SEGMENT_ID_NUM}.`); }); /** * デザイン ID が空(文字型データ項目) */ test('Design ID is blank - set by STRING', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', '456', null); assertError(main, 'Design ID is blank.'); }); /** * Single Send のドラフトを作成する API リクエストのテスト * @param {Object} request * @param request.url * @param request.method * @param request.contentType * @param request.body * @param categories * @param senderId * @param listIds * @param segmentIds * @param unsubscribeGroupId * @param designId * @param subject * @param htmlContent * @param plainContent */ const assertCreateRequest = ({url, method, contentType, body}, categories, senderId, listIds, segmentIds, unsubscribeGroupId, designId, subject, htmlContent, plainContent) => { expect(url).toEqual('https://api.sendgrid.com/v3/marketing/singlesends'); expect(method).toEqual('POST'); expect(contentType).toEqual('application/json'); const bodyObj = JSON.parse(body); expect(bodyObj.name).toEqual(`Questetra-m${processInstance.getProcessModelInfoId()}-p${processInstance.getProcessInstanceId()}`); expect(bodyObj.categories).toEqual(categories); expect(bodyObj.send_to.list_ids).toEqual(listIds); expect(bodyObj.send_to.segment_ids).toEqual(segmentIds); expect(bodyObj.email_config.sender_id).toEqual(senderId); expect(bodyObj.email_config.suppression_group_id).toEqual(unsubscribeGroupId); expect(bodyObj.email_config.design_id).toEqual(designId); expect(bodyObj.email_config.subject).toEqual(subject); expect(bodyObj.email_config.html_content).toEqual(htmlContent); expect(bodyObj.email_config.plain_content).toEqual(plainContent); if (plainContent !== undefined) { expect(bodyObj.email_config.generate_plain_content).toEqual(false); } }; /** * Single Send のドラフトを作成する API リクエストでエラー */ test('Fail to create Single Send', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'design1'); httpClient.setRequestHandler((request) => { assertCreateRequest(request, [], 123, ['list1', 'list2'], ['segment1', 'segment2'], 456, 'design1', undefined, undefined, undefined); return httpClient.createHttpResponse(400, 'application/json', '{}'); }); assertError(main, 'Failed to create single send. status: 400'); }); /** * Single Send の送信予約をする API リクエストのテスト * @param {Object} request * @param request.url * @param request.method * @param request.contentType * @param request.body * @param singleSendId * @param sendAt */ const assertScheduleRequest = ({url, method, contentType, body}, singleSendId, sendAt) => { expect(url).toEqual(`https://api.sendgrid.com/v3/marketing/singlesends/${singleSendId}/schedule`); expect(method).toEqual('PUT'); expect(contentType).toEqual('application/json'); const bodyObj = JSON.parse(body); expect(bodyObj.send_at).toEqual(sendAt); }; /** * Single Send の送信予約をする API リクエストでエラー */ test('Fail to schedule Single Send', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'design1'); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertCreateRequest(request, [], 123, ['list1', 'list2'], ['segment1', 'segment2'], 456, 'design1', undefined, undefined, undefined); reqCount++; return httpClient.createHttpResponse(200, 'application/json', '{"id": "singleSend1"}'); } assertScheduleRequest(request, 'singleSend1', 'now'); return httpClient.createHttpResponse(400, 'application/json', '{}'); }); assertError(main, 'Failed to schedule single send. status: 400, singleSendId: singleSend1'); }); /** * 成功 * デザイン ID で指定 * カテゴリ指定なし * 送信日時指定なし */ test('Succeed - Content set by design ID, no categories, no schduled datetime', () => { const {idDef, urlDef} = prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'design1'); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertCreateRequest(request, [], 123, ['list1', 'list2'], ['segment1', 'segment2'], 456, 'design1', undefined, undefined, undefined); reqCount++; return httpClient.createHttpResponse(200, 'application/json', '{"id": "singleSend1"}'); } assertScheduleRequest(request, 'singleSend1', 'now'); return httpClient.createHttpResponse(200, 'application/json', '{}'); }); main(); // データ項目の値をチェック expect(engine.findData(idDef)).toEqual('singleSend1'); expect(engine.findData(urlDef)).toEqual('https://mc.sendgrid.com/single-sends/singleSend1/stats'); }); /** * 送信日時を設定 * @param timestamp */ const setSendAt = (timestamp) => { const def = engine.createDataDefinition('送信日時', 3, 'q_sendAt', 'DATETIME'); if (timestamp !== null) { engine.setData(def, timestamp); } configs.putObject('conf_SendAt', def); } /** * 送信日時が選択されているのに、値が空 */ test('Scheduled Datetime is null', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'design1'); setSendAt(null); assertError(main, 'Scheduled Datetime is selected but its data is null.'); }); /** * 送信日時が過去 */ test('Scheduled Datetime has passed', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'design1'); const timestamp = new com.questetra.bpms.util.AddableTimestamp().addMinutes(-1); setSendAt(timestamp); assertError(main, 'Scheduled Datetime must be future.'); }); /** * 成功 * デザイン ID で指定 * リストのみ指定し、セグメント指定なし * カテゴリ指定あり * 送信日時指定あり */ test('Succeed - Content set by design ID, no segments, with categories, with schduled datetime', () => { const {idDef, urlDef} = prepareConfigs('category1\ncategory2\ncategory3', '1', 'list1', null, '4', 'design2'); const timestamp = new com.questetra.bpms.util.AddableTimestamp().addMinutes(3); setSendAt(timestamp); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertCreateRequest(request, ['category1', 'category2', 'category3'], 1, ['list1'], [], 4, 'design2', undefined, undefined, undefined); reqCount++; return httpClient.createHttpResponse(200, 'application/json', '{"id": "singleSend2"}'); } assertScheduleRequest(request, 'singleSend2', dateFormatter.format('UTC', "yyyy-MM-dd'T'HH:mm:ss'Z'", timestamp)); return httpClient.createHttpResponse(200, 'application/json', '{}'); }); main(); // データ項目の値をチェック expect(engine.findData(idDef)).toEqual('singleSend2'); expect(engine.findData(urlDef)).toEqual('https://mc.sendgrid.com/single-sends/singleSend2/stats'); }); /** * 成功 * デザイン ID で指定 * セグメントのみ指定し、リスト指定なし * カテゴリ指定あり * 送信日時指定なし * データ項目に保存しない */ test('Succeed - Content set by design ID, no lists, with categories, no schduled datetime, not save', () => { const {idDef, urlDef} = prepareConfigs('category1', '1000', null, 'segment1', '4000', 'design3'); configs.put('conf_SingleSendId', ''); configs.put('conf_SingleSendUrl', ''); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertCreateRequest(request, ['category1'], 1000, [], ['segment1'], 4000, 'design3', undefined, undefined, undefined); reqCount++; return httpClient.createHttpResponse(200, 'application/json', '{"id": "singleSend3"}'); } assertScheduleRequest(request, 'singleSend3', 'now'); return httpClient.createHttpResponse(200, 'application/json', '{}'); }); main(); // データ項目の値をチェック expect(engine.findData(idDef)).toEqual('事前文字列'); expect(engine.findData(urlDef)).toEqual('事前文字列'); }); /** * 成功 * デザイン ID で指定 * カテゴリ、リスト ID、セグメント ID を最大個数指定し、API リクエストの確認を省略 */ test('Succeed - Maximum number of categories, listIds and segmentIds', () => { const categoriesStr = createListString(MAX_CATEGORY_NUM - 1) + createString(MAX_CATEGORY_LENGTH); const listIdsStr = createListString(MAX_LIST_ID_NUM); const segmentIdsStr = createListString(MAX_SEGMENT_ID_NUM); const {idDef, urlDef} = prepareConfigs(categoriesStr, '1', listIdsStr, segmentIdsStr, '4', 'design2'); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { // API リクエストの確認を省略 reqCount++; return httpClient.createHttpResponse(200, 'application/json', '{"id": "singleSend1"}'); } assertScheduleRequest(request, 'singleSend1', 'now'); return httpClient.createHttpResponse(200, 'application/json', '{}'); }); main(); // データ項目の値をチェック expect(engine.findData(idDef)).toEqual('singleSend1'); expect(engine.findData(urlDef)).toEqual('https://mc.sendgrid.com/single-sends/singleSend1/stats'); }); /** * 「デザインを使用せず、件名と本文を直接指定する」がオンなのに、デザイン ID が文字型データ項目で指定されている */ test('Design ID is set by STRING while hasUniqueContent is enabled', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', '456', null); // 値が null でもエラー configs.putObject('conf_HasUniqueContent', true); assertError(main, 'Design ID is set while "Configure the subject and content without using Design" is enabled.'); }); /** * 本文を直接指定 * @param subject * @param htmlContent * @param plainContent */ const setUniqueContent = (subject, htmlContent, plainContent) => { configs.putObject('conf_HasUniqueContent', true); configs.put('conf_DesignId', ''); configs.put('conf_Subject', subject); configs.put('conf_HtmlContent', htmlContent); configs.put('conf_PlainContent', plainContent); } /** * 「デザインを使用せず、件名と本文を直接指定する」がオンなのに、件名が空 */ test('Subject is blank', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'dummyDesignId'); setUniqueContent('', 'メールの HTML 本文', ''); assertError(main, 'Subject is blank.'); }); /** * 「デザインを使用せず、件名と本文を直接指定する」がオンなのに、HTML 本文が空 */ test('HTML Content is Blank', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'dummyDesignId'); setUniqueContent('メールの件名', '', ''); assertError(main, 'HTML Content is blank.'); }); /** * 成功 * 件名、本文を直接指定 * プレーンテキストメールの本文は指定なし */ test('Succeed - Has unique content, without plain text content', () => { const {idDef, urlDef} = prepareConfigs(null, '1', 'list1', null, '4', 'dummyDesignId'); const subject = 'メールの件名'; const htmlContent = 'HTML メールの本文\nこれは HTML メールの本文です'; setUniqueContent(subject, htmlContent, ''); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertCreateRequest(request, [], 1, ['list1'], [], 4, undefined, subject, htmlContent, undefined); reqCount++; return httpClient.createHttpResponse(200, 'application/json', '{"id": "singleSend4"}'); } assertScheduleRequest(request, 'singleSend4', 'now'); return httpClient.createHttpResponse(200, 'application/json', '{}'); }); main(); // データ項目の値をチェック expect(engine.findData(idDef)).toEqual('singleSend4'); expect(engine.findData(urlDef)).toEqual('https://mc.sendgrid.com/single-sends/singleSend4/stats'); }); /** * 成功 * 件名、本文を直接指定 * プレーンテキストメールの本文の指定あり */ test('Succeed - Has unique content, with plain text content', () => { const {idDef, urlDef} = prepareConfigs(null, '1', 'list1', null, '4', 'dummyDesignId'); const subject = 'メールの件名'; const htmlContent = 'HTML メールの 本文\nこれは HTML メールの本文です'; const plainContent = 'プレーンテキストメールの本文\nこれはプレーンテキストメールの本文です'; setUniqueContent(subject, htmlContent, plainContent); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertCreateRequest(request, [], 1, ['list1'], [], 4, undefined, subject, htmlContent, plainContent); reqCount++; return httpClient.createHttpResponse(200, 'application/json', '{"id": "singleSend5"}'); } assertScheduleRequest(request, 'singleSend5', 'now'); return httpClient.createHttpResponse(200, 'application/json', '{}'); }); main(); // データ項目の値をチェック expect(engine.findData(idDef)).toEqual('singleSend5'); expect(engine.findData(urlDef)).toEqual('https://mc.sendgrid.com/single-sends/singleSend5/stats'); }); /** * 設定を固定値で上書き * @param senderId * @param unsubscribeGroupId * @param designId */ const updateConfigsWithFixedValues = (unsubscribeGroupId, designId) => { configs.put('conf_UnsubscribeGroupId', unsubscribeGroupId); configs.put('conf_DesignId', designId); }; /** * デザイン ID が空(固定値) */ test('Design ID is blank - set as fixed value', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', 'dummyId', 'dummyId'); updateConfigsWithFixedValues('456', ''); assertError(main, 'Design ID is blank.'); }); /** * 「デザインを使用せず、件名と本文を直接指定する」がオンなのに、デザイン ID が固定値で指定されている */ test('Design ID is set as fixed value while hasUniqueContent is enabled', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', 'dummyId', 'dummyId'); updateConfigsWithFixedValues('456', 'design1'); configs.putObject('conf_HasUniqueContent', true); assertError(main, 'Design ID is set while "Configure the subject and content without using Design" is enabled.'); }); /** * 成功 * 配信停止グループ ID、デザイン ID を固定値で指定 */ test('Succeed - Unsubscribe Group ID and Design ID are set as fixed value', () => { const {idDef, urlDef} = prepareConfigs(null, '123', 'list1', null, 'dummyId', 'dummyId'); updateConfigsWithFixedValues('456', 'design1'); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertCreateRequest(request, [], 123, ['list1'], [], 456, 'design1', undefined, undefined, undefined); reqCount++; return httpClient.createHttpResponse(200, 'application/json', '{"id": "singleSend11"}'); } assertScheduleRequest(request, 'singleSend11', 'now'); return httpClient.createHttpResponse(200, 'application/json', '{}'); }); main(); // データ項目の値をチェック expect(engine.findData(idDef)).toEqual('singleSend11'); expect(engine.findData(urlDef)).toEqual('https://mc.sendgrid.com/single-sends/singleSend11/stats'); }); /** * 選択型データ設定用のオブジェクトを作成 * @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; }; /** * カテゴリの個数が多すぎる(選択型データ項目) */ test('Too many Categories - set by SELECT', () => { prepareConfigs('dummy', '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'design1'); 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('dummy', '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'design1'); 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('dummy', '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'design1'); 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.`); }); /** * 配信停止グループ ID が未選択(選択型データ項目) */ test('Unsubscribe Group ID is not selected - set by SELECT', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', 'dummy', 'design1'); setDataItem('UnsubscribeGroupId', 23, 'SELECT_SINGLE', new java.util.ArrayList()); assertError(main, 'Unsubscribe Group ID is not selected.'); }); /** * 配信停止グループ ID が整数でない(選択型データ項目) */ test('Unsubscribe Group ID is not integer - set by SELECT', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', '123', 'design1'); setDataItem('UnsubscribeGroupId', 23, 'SELECT_SINGLE', prepareSelects('invalidId', 1)); assertError(main, 'Unsubscribe Group ID must be integer.'); }); /** * リスト ID とセグメント ID がどちらも未選択(選択型データ項目) */ test('No List IDs or Segment IDs - set by SELECT', () => { prepareConfigs(null, '123', 'dummy', 'dummy', '456', 'design1'); setDataItem('ListIds', 24, 'SELECT_CHECKBOX', new java.util.ArrayList()); setDataItem('SegmentIds', 25, 'SELECT_CHECKBOX', new java.util.ArrayList()); assertError(main, 'No List IDs or Segment IDs.'); }); /** * リスト ID の個数が多すぎる(選択型データ項目) */ test('Too many List IDs - set by SELECT', () => { prepareConfigs(null, '123', 'dummy', null, '456', 'design1'); setDataItem('ListIds', 24, 'SELECT_CHECKBOX', prepareSelects('list_', MAX_LIST_ID_NUM + 1)); assertError(main, `The maximum number of List IDs is ${MAX_LIST_ID_NUM}.`); }); /** * セグメント ID の個数が多すぎる(選択型データ項目) */ test('Too many Segment IDs - set by SELECT', () => { prepareConfigs(null, '123', null, 'dummy', '456', 'design1'); setDataItem('SegmentIds', 25, 'SELECT_CHECKBOX', prepareSelects('segment_', MAX_SEGMENT_ID_NUM + 1)); assertError(main, `The maximum number of Segment IDs is ${MAX_SEGMENT_ID_NUM}.`); }); /** * デザイン ID が未選択(選択型データ項目) */ test('Design ID is not selected - set by SELECT', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'dummy'); setDataItem('DesignId', 26, 'SELECT_SINGLE', new java.util.ArrayList()); assertError(main, 'Design ID is not selected.'); }); /** * 「デザインを使用せず、件名と本文を直接指定する」がオンなのに、デザイン ID が選択型データ項目で指定されている */ test('Design ID is set by SELECT while hasUniqueContent is enabled', () => { prepareConfigs(null, '123', 'list1\nlist2', 'segment1\nsegment2', '456', 'dummy'); setDataItem('DesignId', 26, 'SELECT_SINGLE', new java.util.ArrayList()); // 未選択でもエラー configs.putObject('conf_HasUniqueContent', true); assertError(main, 'Design ID is set while "Configure the subject and content without using Design" is enabled.'); }); /** * 成功 * データ項目で指定できるものは、すべて選択型データ項目で指定 * デザイン ID で指定 * カテゴリ指定なし * リスト ID のみ指定 * 送信日時指定なし */ test('Succeed - Configured by SELECT, content set by design ID, no categories, no schduled datetime', () => { // 認証設定を準備 const auth = httpClient.createAuthSettingToken('SendGrid API Key', 'sendgrid-1234567'); configs.putObject('conf_Auth', auth); const idDef = setDataItem('SingleSendId', 11, 'STRING_TEXTFIELD', '事前文字列'); const urlDef = setDataItem('SingleSendUrl', 12, 'STRING_TEXTFIELD', '事前文字列'); setDataItem('Categories', 21, 'SELECT_CHECKBOX', new java.util.ArrayList()); configs.put('conf_SenderId', '123'); setDataItem('ListIds', 22, 'SELECT_CHECKBOX', prepareSelects('list', 2)); setDataItem('SegmentIds', 23, 'SELECT_CHECKBOX', new java.util.ArrayList()); setDataItem('UnsubscribeGroupId', 24, 'SELECT_SINGLE', prepareSelects('', 1)); // 整数にするため、prefix を空に setDataItem('DesignId', 25, 'SELECT_SINGLE', prepareSelects('design', 1)); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertCreateRequest(request, [], 123, ['list1', 'list2'], [], 1, 'design1', undefined, undefined, undefined); reqCount++; return httpClient.createHttpResponse(200, 'application/json', '{"id": "singleSend1"}'); } assertScheduleRequest(request, 'singleSend1', 'now'); return httpClient.createHttpResponse(200, 'application/json', '{}'); }); main(); // データ項目の値をチェック expect(engine.findData(idDef)).toEqual('singleSend1'); expect(engine.findData(urlDef)).toEqual('https://mc.sendgrid.com/single-sends/singleSend1/stats'); }); /** * 成功 * データ項目で指定できるものは、すべて選択型データ項目で指定 * デザイン ID で指定 * カテゴリ指定あり * セグメント ID のみ指定 * 送信日時指定なし */ test('Succeed - Configured by SELECT, content set by design ID, with categories, no schduled datetime', () => { // 認証設定を準備 const auth = httpClient.createAuthSettingToken('SendGrid API Key', 'sendgrid-1234567'); configs.putObject('conf_Auth', auth); const idDef = setDataItem('SingleSendId', 11, 'STRING_TEXTFIELD', '事前文字列'); const urlDef = setDataItem('SingleSendUrl', 12, 'STRING_TEXTFIELD', '事前文字列'); setDataItem('Categories', 21, 'SELECT_CHECKBOX', prepareSelects('category', 3)); configs.put('conf_SenderId', '123'); setDataItem('ListIds', 22, 'SELECT_CHECKBOX', new java.util.ArrayList()); setDataItem('SegmentIds', 23, 'SELECT_CHECKBOX', prepareSelects('segment', 2)); setDataItem('UnsubscribeGroupId', 24, 'SELECT_SINGLE', prepareSelects('', 1)); // 整数にするため、prefix を空に setDataItem('DesignId', 25, 'SELECT_SINGLE', prepareSelects('design', 1)); let reqCount = 0; httpClient.setRequestHandler((request) => { if (reqCount === 0) { assertCreateRequest(request, ['category1', 'category2', 'category3'], 123, [], ['segment1', 'segment2'], 1, 'design1', undefined, undefined, undefined); reqCount++; return httpClient.createHttpResponse(200, 'application/json', '{"id": "singleSend2"}'); } assertScheduleRequest(request, 'singleSend2', 'now'); return httpClient.createHttpResponse(200, 'application/json', '{}'); }); main(); // データ項目の値をチェック expect(engine.findData(idDef)).toEqual('singleSend2'); expect(engine.findData(urlDef)).toEqual('https://mc.sendgrid.com/single-sends/singleSend2/stats'); }); ]]>