Skip to content

Commit

Permalink
DEVEXP-515: E2E SMS/Batches (#123)
Browse files Browse the repository at this point in the history
  • Loading branch information
asein-sinch authored Aug 19, 2024
1 parent f3c1660 commit cf9789a
Show file tree
Hide file tree
Showing 6 changed files with 272 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ export class ExceptionResponse<
);
} else if (!res) {
res = {} as V;
if (context.response.status !== 204 && context.response.status !== 200) {
if (context.response.status !== 204
&& context.response.status !== 200
&& context.response.status !== 202
) {
res = {} as V;
error = new EmptyResponseError<V>(
context.response.statusText,
Expand Down
8 changes: 8 additions & 0 deletions packages/sms/cucumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
default: [
'tests/e2e/features/**/*.feature',
'--require-module ts-node/register',
'--require tests/rest/v1/**/*.steps.ts',
`--format-options '{"snippetInterface": "synchronous"}'`,
].join(' '),
};
3 changes: 2 additions & 1 deletion packages/sms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"scripts": {
"build": "yarn run clean && yarn run compile",
"clean": "rimraf dist tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo",
"compile": "tsc -p tsconfig.build.json && tsc -p tsconfig.tests.json && rimraf dist/tests tsconfig.build.tsbuildinfo"
"compile": "tsc -p tsconfig.build.json && tsc -p tsconfig.tests.json && rimraf dist/tests tsconfig.build.tsbuildinfo",
"test:e2e": "cucumber-js"
},
"dependencies": {
"@sinch/sdk-client": "^1.1.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export interface DryRunResponsePerRecipientInner {

recipient?: string;
message_part?: string;
number_of_parts?: number;
body?: string;
encoding?: string;
}
Expand Down
2 changes: 0 additions & 2 deletions packages/sms/src/rest/v1/batches/batches-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ export class BatchesApi extends SmsDomainApi {
*/
public async dryRun(data: DryRunRequestData): Promise<DryRunResponse> {
this.client = this.getSinchClient();
data['number_of_recipients'] = data['number_of_recipients'] !== undefined ? data['number_of_recipients'] : 100;
const getParams = this.client.extractQueryParams<DryRunRequestData>(data, [
'per_recipient',
'number_of_recipients']);
Expand Down Expand Up @@ -164,7 +163,6 @@ export class BatchesApi extends SmsDomainApi {
*/
public list(data: ListBatchesRequestData): ApiListPromise<SendSMSResponse> {
this.client = this.getSinchClient();
data['page_size'] = data['page_size'] !== undefined ? data['page_size'] : 30;
const getParams = this.client.extractQueryParams<ListBatchesRequestData>(
data,
['page', 'page_size', 'from', 'start_date', 'end_date', 'client_reference'],
Expand Down
257 changes: 257 additions & 0 deletions packages/sms/tests/rest/v1/batches/batches.steps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
import { BatchesApi, SmsService, Sms } from '../../../../src';
import { Given, When, Then } from '@cucumber/cucumber';
import * as assert from 'assert';
import { PageResult } from '@sinch/sdk-client';

let batchesApi: BatchesApi;
let sendSmsResponse: Sms.TextResponse;
let dryRunResponse: Sms.DryRunResponse;
let listResponse: PageResult<Sms.SendSMSResponse>;
let batchesList: Sms.SendSMSResponse[];
let pagesIteration: number;
let batch: Sms.SendSMSResponse;
let deliveryFeedbackResponse: void;

Given('the SMS service "Batches" is available', () => {
const smsService = new SmsService({
projectId: 'tinyfrog-jump-high-over-lilypadbasin',
keyId: 'keyId',
keySecret: 'keySecret',
authHostname: 'http://localhost:3011',
smsHostname: 'http://localhost:3017',
});
batchesApi = smsService.batches;
});

When('I send a request to send a text message', async () => {
const sendSmsRequest: Sms.SendTextSMSRequestData = {
sendSMSRequestBody: {
body: 'SMS body message',
to: ['+12017777777'],
from: '+12015555555',
send_at: new Date('2024-06-06T09:25:00Z'),
delivery_report: 'full',
feedback_enabled: true,
},
};
sendSmsResponse = await batchesApi.sendTextMessage(sendSmsRequest);
});

Then('the response contains the text SMS details', () => {
assert.equal(sendSmsResponse.id, '01W4FFL35P4NC4K35SMSBATCH1');
assert.deepEqual(sendSmsResponse.to, ['12017777777']);
assert.equal(sendSmsResponse.from, '12015555555');
assert.equal(sendSmsResponse.canceled, false);
assert.equal(sendSmsResponse.body, 'SMS body message');
assert.equal(sendSmsResponse.type, 'mt_text');
assert.deepEqual(sendSmsResponse.created_at, new Date('2024-06-06T09:22:14.304Z'));
assert.deepEqual(sendSmsResponse.modified_at, new Date('2024-06-06T09:22:14.304Z'));
const fullDeliveryReport: Sms.DeliveryReportEnum = 'full';
assert.equal(sendSmsResponse.delivery_report, fullDeliveryReport);
assert.deepEqual(sendSmsResponse.send_at, new Date('2024-06-06T09:25:00Z'));
assert.deepEqual(sendSmsResponse.expire_at, new Date('2024-06-09T09:25:00Z'));
assert.equal(sendSmsResponse.feedback_enabled, true);
assert.equal(sendSmsResponse.flash_message, false);
});

When('I send a request to perform a dry run of a batch', async () => {
const sendSmsRequest: Sms.DryRunRequestData = {
dryRunRequestBody: {
from: '+12015555555',
to: [
'+12017777777',
'+12018888888',
'+12019999999',
],
parameters: {
name: {
'+12017777777': 'John',
default: 'there',
},
},
body: 'Hello ${name}!',
delivery_report: 'none',
type: 'mt_text',
},
};
dryRunResponse = await batchesApi.dryRun(sendSmsRequest);
});

Then('the response contains the calculated bodies and number of parts for all messages in the batch', () => {
assert.equal(dryRunResponse.number_of_messages, 3);
assert.equal(dryRunResponse.number_of_recipients, 3);
assert.ok(dryRunResponse.per_recipient);
assert.equal(dryRunResponse.per_recipient.length, 3);
const johnMessage = dryRunResponse.per_recipient.filter(
(perRecipient) => perRecipient.recipient === '12017777777',
).pop();
assert.ok(johnMessage);
assert.equal(johnMessage.body, 'Hello John!');
assert.equal(johnMessage.number_of_parts, 1);
assert.equal(johnMessage.encoding, 'text');
const defaultMessage = dryRunResponse.per_recipient.filter(
(perRecipient) => perRecipient.recipient === '12018888888',
).pop();
assert.ok(defaultMessage);
assert.equal(defaultMessage.body, 'Hello there!');
assert.equal(defaultMessage.number_of_parts, 1);
assert.equal(defaultMessage.encoding, 'text');
});

When('I send a request to list the SMS batches', async () => {
const listBatchRequest: Sms.ListBatchesRequestData = {
page_size: 2,
};
listResponse = await batchesApi.list(listBatchRequest);
});

Then('the response contains {string} SMS batches', (expectedAnswer: string) => {
const expectedBatchesCount = parseInt(expectedAnswer, 10);
assert.equal(listResponse.data.length, expectedBatchesCount);
});

When('I send a request to list all the SMS batches', async () => {
batchesList = [];
for await (const batch of batchesApi.list({ page_size: 2 })) {
batchesList.push(batch);
}
});

When('I iterate manually over the SMS batches pages', async () => {
batchesList = [];
listResponse = await batchesApi.list({
page_size: 2,
});
batchesList.push(...listResponse.data);
pagesIteration = 1;
let reachedEndOfPages = false;
while (!reachedEndOfPages) {
if (listResponse.hasNextPage) {
listResponse = await listResponse.nextPage();
batchesList.push(...listResponse.data);
pagesIteration++;
} else {
reachedEndOfPages = true;
}
}
});

Then('the SMS batches list contains {string} SMS batches', (expectedAnswer: string) => {
const expectedBatchesCount = parseInt(expectedAnswer, 10);
assert.equal(batchesList.length, expectedBatchesCount);
});

Then('the SMS batches iteration result contains the data from {string} pages', (expectedAnswer: string) => {
const expectedPagesCount = parseInt(expectedAnswer, 10);
assert.equal(pagesIteration, expectedPagesCount);
});

When('I send a request to retrieve an SMS batch', async () => {
batch = await batchesApi.get({
batch_id: '01W4FFL35P4NC4K35SMSBATCH1',
});
});

Then('the response contains the SMS batch details', () => {
assert.equal(batch.id, '01W4FFL35P4NC4K35SMSBATCH1');
assert.deepEqual(sendSmsResponse.to, ['12017777777']);
assert.equal(sendSmsResponse.from, '12015555555');
assert.equal(sendSmsResponse.canceled, false);
assert.equal(sendSmsResponse.body, 'SMS body message');
assert.equal(sendSmsResponse.type, 'mt_text');
assert.deepEqual(sendSmsResponse.created_at, new Date('2024-06-06T09:22:14.304Z'));
assert.deepEqual(sendSmsResponse.modified_at, new Date('2024-06-06T09:22:14.304Z'));
const fullDeliveryReport: Sms.DeliveryReportEnum = 'full';
assert.equal(sendSmsResponse.delivery_report, fullDeliveryReport);
assert.deepEqual(sendSmsResponse.send_at, new Date('2024-06-06T09:25:00Z'));
assert.deepEqual(sendSmsResponse.expire_at, new Date('2024-06-09T09:25:00Z'));
assert.equal(sendSmsResponse.feedback_enabled, true);
assert.equal(sendSmsResponse.flash_message, false);
});

When('I send a request to update an SMS batch', async () => {
batch = await batchesApi.update({
batch_id: '01W4FFL35P4NC4K35SMSBATCH1',
updateBatchMessageRequestBody: {
from: '+12016666666',
to_add: [
'01W4FFL35P4NC4K35SMSGROUP1',
],
delivery_report: 'summary',
},
});
});

Then('the response contains the SMS batch details with updated data', () => {
assert.equal(batch.id, '01W4FFL35P4NC4K35SMSBATCH1');
assert.deepEqual(batch.to, ['12017777777', '01W4FFL35P4NC4K35SMSGROUP1']);
assert.equal(batch.from, '12016666666');
assert.equal(batch.canceled, false);
assert.equal(batch.body, 'SMS body message');
assert.equal(batch.type, 'mt_text');
assert.deepEqual(batch.created_at, new Date('2024-06-06T09:22:14.304Z'));
assert.deepEqual(batch.modified_at, new Date('2024-06-06T09:22:48.054Z'));
const summaryDeliveryReport: Sms.DeliveryReportEnum = 'summary';
assert.equal(batch.delivery_report, summaryDeliveryReport);
assert.deepEqual(batch.send_at, new Date('2024-06-06T09:25:00Z'));
assert.deepEqual(batch.expire_at, new Date('2024-06-09T09:25:00Z'));
assert.equal(batch.feedback_enabled, true);
assert.equal((batch as Sms.TextResponse).flash_message, false);
});

When('I send a request to replace an SMS batch', async () => {
batch = await batchesApi.replace({
batch_id: '01W4FFL35P4NC4K35SMSBATCH1',
replaceBatchMessageRequestBody: {
from: '+12016666666',
to: [
'+12018888888',
],
body: 'This is the replacement batch',
send_at: new Date('2024-06-06T09:35:00Z'),
},
});
});

Then('the response contains the new SMS batch details with the provided data for replacement', () => {
assert.equal(batch.id, '01W4FFL35P4NC4K35SMSBATCH1');
assert.deepEqual(batch.to, ['12018888888']);
assert.equal(batch.from, '12016666666');
assert.equal(batch.canceled, false);
assert.equal(batch.body, 'This is the replacement batch');
assert.equal(batch.type, 'mt_text');
assert.deepEqual(batch.created_at, new Date('2024-06-06T09:22:14.304Z'));
assert.deepEqual(batch.modified_at, new Date('2024-06-06T09:23:32.504Z'));
const noDeliveryReport: Sms.DeliveryReportEnum = 'none';
assert.equal(batch.delivery_report, noDeliveryReport);
assert.deepEqual(batch.send_at, new Date('2024-06-06T09:35:00Z'));
assert.deepEqual(batch.expire_at, new Date('2024-06-09T09:35:00Z'));
assert.equal(batch.feedback_enabled, undefined);
assert.equal((batch as Sms.TextResponse).flash_message, false);
});

When('I send a request to cancel an SMS batch', async () => {
batch = await batchesApi.cancel({
batch_id: '01W4FFL35P4NC4K35SMSBATCH1',
});
});

Then('the response contains the SMS batch details with a cancelled status', () => {
assert.equal(batch.id, '01W4FFL35P4NC4K35SMSBATCH1');
assert.equal(batch.canceled, true);
});

When('I send a request to send delivery feedbacks', async () => {
deliveryFeedbackResponse = await batchesApi.sendDeliveryFeedback({
batch_id: '01W4FFL35P4NC4K35SMSBATCH1',
deliveryFeedbackRequestBody: {
recipients: [
'+12017777777',
],
},
});
});

Then('the delivery feedback response contains no data', () => {
assert.deepEqual(deliveryFeedbackResponse, {});
});

0 comments on commit cf9789a

Please sign in to comment.