diff --git a/README.md b/README.md index 2a112b7..1e4d7d3 100644 --- a/README.md +++ b/README.md @@ -450,6 +450,13 @@ api.triggerBroadcast(1, { name: "foo" }, { emails: ["example@emails.com"], email [You can learn more about the available recipient fields here](https://customer.io/docs/api/#operation/triggerBroadcast). +Both `data` and `recipients` are optional. Omitting `recipients` sends the broadcast to its configured recipients. Note that the parameters are positional: to pass `recipients` without `data`, pass `undefined` for `data` — passing the recipient selector as the second argument would send it as liquid data instead. + +```javascript +api.triggerBroadcast(1); // broadcast's configured recipients +api.triggerBroadcast(1, undefined, { emails: ["example@emails.com"], email_ignore_missing: true }); +``` + #### Options - **id**: String or number (required) diff --git a/lib/api.ts b/lib/api.ts index d41c19c..9147994 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -221,24 +221,37 @@ export class APIClient { * Otherwise the entire `recipients` object is forwarded verbatim alongside * `data` (use this for segment-based recipients). * + * Both `data` and `recipients` are optional; omitting `recipients` sends the + * broadcast to its configured recipients. + * + * Note that the parameters are positional: to pass `recipients` without + * `data`, pass `undefined` for `data` — e.g. + * `triggerBroadcast(1, undefined, { emails: ['user@example.com'] })`. + * Passing the recipient selector as the second argument would send it as + * liquid `data` and trigger the broadcast's configured recipients instead. + * * @param broadcastId The broadcast (campaign) id. * @param data Liquid `data` payload made available to the broadcast template. * @param recipients Recipient selector. See above. * @returns The parsed JSON response body. */ - triggerBroadcast(broadcastId: string | number, data: RequestData, recipients: Recipients) { - let payload = {}; - let customRecipientField = ( - Object.keys(BROADCASTS_ALLOWED_RECIPIENT_FIELDS) as BroadcastsAllowedRecipientFieldsKeys[] - ).find((field) => recipients[field]); - - if (customRecipientField) { - payload = Object.assign({ data }, filterRecipientsDataForField(recipients, customRecipientField)); - } else { - payload = { - data, - recipients, - }; + triggerBroadcast(broadcastId: string | number, data?: RequestData, recipients?: Recipients) { + let payload: Record = {}; + + if (data && Object.keys(data).length > 0) { + payload.data = data; + } + + if (recipients && Object.keys(recipients).length > 0) { + let customRecipientField = ( + Object.keys(BROADCASTS_ALLOWED_RECIPIENT_FIELDS) as BroadcastsAllowedRecipientFieldsKeys[] + ).find((field) => recipients[field]); + + if (customRecipientField) { + payload = Object.assign(payload, filterRecipientsDataForField(recipients, customRecipientField)); + } else { + payload.recipients = recipients; + } } return this.request.post(`${this.apiRoot}/campaigns/${encodeURIComponent(broadcastId)}/triggers`, payload); diff --git a/test/api.ts b/test/api.ts index 9127a41..8cac3e3 100644 --- a/test/api.ts +++ b/test/api.ts @@ -390,6 +390,39 @@ test('#triggerBroadcast discards extraneous fields', (t) => { ); }); +test('#triggerBroadcast works with broadcastId only', (t) => { + sinon.stub(t.context.client.request, 'post'); + t.context.client.triggerBroadcast(1); + t.truthy((t.context.client.request.post as SinonStub).calledWith(`${RegionUS.apiUrl}/campaigns/1/triggers`, {})); +}); + +test('#triggerBroadcast works with data and no recipients', (t) => { + sinon.stub(t.context.client.request, 'post'); + t.context.client.triggerBroadcast(1, { type: 'data' }); + t.truthy( + (t.context.client.request.post as SinonStub).calledWith(`${RegionUS.apiUrl}/campaigns/1/triggers`, { + data: { type: 'data' }, + }), + ); +}); + +test('#triggerBroadcast works with recipients and no data', (t) => { + sinon.stub(t.context.client.request, 'post'); + t.context.client.triggerBroadcast(1, undefined, { emails: ['test@email.com'], email_ignore_missing: true }); + t.truthy( + (t.context.client.request.post as SinonStub).calledWith(`${RegionUS.apiUrl}/campaigns/1/triggers`, { + emails: ['test@email.com'], + email_ignore_missing: true, + }), + ); +}); + +test('#triggerBroadcast omits empty data and recipients objects', (t) => { + sinon.stub(t.context.client.request, 'post'); + t.context.client.triggerBroadcast(1, {}, {}); + t.truthy((t.context.client.request.post as SinonStub).calledWith(`${RegionUS.apiUrl}/campaigns/1/triggers`, {})); +}); + test('#listExports: success', (t) => { sinon.stub(t.context.client.request, 'get'); t.context.client.listExports();