diff --git a/.github/workflows/run-ci.yaml b/.github/workflows/run-ci.yaml index 846bee5f..cae140be 100644 --- a/.github/workflows/run-ci.yaml +++ b/.github/workflows/run-ci.yaml @@ -32,10 +32,6 @@ jobs: token: ${{ secrets.PAT_CI }} fetch-depth: 0 path: sinch-sdk-mockserver - - name: Build custom Docker image - run: | - cd sinch-sdk-mockserver - docker build -t sinch-sdk-mockserver -f Dockerfile . - name: Install Docker Compose run: | sudo apt-get update @@ -44,11 +40,6 @@ jobs: run: | cd sinch-sdk-mockserver docker-compose up -d - - name: Wait for the mock servers to be healthy - run: | - cd sinch-sdk-mockserver - chmod +x ./scripts/healthcheck.sh - ./scripts/healthcheck.sh - name: Create target directories for feature files run: | mkdir -p ./packages/fax/tests/e2e/features @@ -57,6 +48,7 @@ jobs: mkdir -p ./packages/elastic-sip-trunking/tests/e2e/features mkdir -p ./packages/sms/tests/e2e/features mkdir -p ./packages/verification/tests/e2e/features + mkdir -p ./packages/voice/tests/e2e/features - name: Copy feature files run: | cp sinch-sdk-mockserver/features/fax/*.feature ./packages/fax/tests/e2e/features/ @@ -65,6 +57,7 @@ jobs: cp sinch-sdk-mockserver/features/elastic-sip-trunking/*.feature ./packages/elastic-sip-trunking/tests/e2e/features/ cp sinch-sdk-mockserver/features/sms/*.feature ./packages/sms/tests/e2e/features/ cp sinch-sdk-mockserver/features/verification/*.feature ./packages/verification/tests/e2e/features/ + cp sinch-sdk-mockserver/features/voice/*.feature ./packages/voice/tests/e2e/features/ - name: Run e2e tests run: | yarn install diff --git a/packages/voice/cucumber.js b/packages/voice/cucumber.js new file mode 100644 index 00000000..691a9809 --- /dev/null +++ b/packages/voice/cucumber.js @@ -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(' '), +}; diff --git a/packages/voice/package.json b/packages/voice/package.json index 473628fc..3a5528f4 100644 --- a/packages/voice/package.json +++ b/packages/voice/package.json @@ -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" diff --git a/packages/voice/src/models/v1/conference-callout-request/conference-callout-request.ts b/packages/voice/src/models/v1/conference-callout-request/conference-callout-request.ts index 6d7583da..54a96829 100644 --- a/packages/voice/src/models/v1/conference-callout-request/conference-callout-request.ts +++ b/packages/voice/src/models/v1/conference-callout-request/conference-callout-request.ts @@ -1,5 +1,6 @@ import { Destination } from '../destination'; import { ConferenceDtmfOptions } from '../conference-dtmf-options'; +import { MusicOnHold } from '../enums'; /** * The conference callout calls a phone number or a user. When the call is answered, it's connected to a conference room. @@ -28,7 +29,7 @@ export interface ConferenceCalloutRequest { /** The text that will be spoken as a greeting. */ greeting?: string; /** Means "music-on-hold." It's an optional parameter that specifies what the first participant should listen to while they're alone in the conference, waiting for other participants to join. It can take one of these pre-defined values:
If no “music-on-hold” is specified, the user will only hear silence. */ - mohClass?: string; + mohClass?: MusicOnHold; /** Used to input custom data. */ custom?: string; /** can be either “pstn” for PSTN endpoint or “mxp” for data (app or web) clients. */ diff --git a/packages/voice/tests/rest/v1/callouts/callouts.steps.ts b/packages/voice/tests/rest/v1/callouts/callouts.steps.ts new file mode 100644 index 00000000..4f2662dd --- /dev/null +++ b/packages/voice/tests/rest/v1/callouts/callouts.steps.ts @@ -0,0 +1,121 @@ +import { CalloutsApi, VoiceService, Voice } from '../../../../src'; +import { Given, When, Then } from '@cucumber/cucumber'; +import * as assert from 'assert'; + +let calloutsApi: CalloutsApi; +let ttsCallResponse: Voice.CalloutResponse; + +Given('the Voice service "Callouts" is available', () => { + const voiceService = new VoiceService({ + applicationKey: 'appKey', + applicationSecret: 'appSecret', + voiceHostname: 'http://localhost:3019', + }); + calloutsApi = voiceService.callouts; +}); + +When('I send a request to make a TTS call', async () => { + ttsCallResponse = await calloutsApi.tts({ + ttsCalloutRequestBody: { + method: 'ttsCallout', + ttsCallout: { + cli: '+12015555555', + destination: { + type: 'number', + endpoint: '+12017777777', + }, + locale: 'en-US', + text: 'Hello, this is a call from Sinch.', + }, + }, + }); +}); + +Then('the callout response contains the TTS call ID', () => { + assert.equal(ttsCallResponse.callId, '1ce0ffee-ca11-ca11-ca11-abcdef000001'); +}); + +When('I send a request to make a Conference call with the "Callout" service', async () => { + ttsCallResponse = await calloutsApi.conference({ + conferenceCalloutRequestBody: { + method: 'conferenceCallout', + conferenceCallout: { + cli: '+12015555555', + destination: { + type: 'number', + endpoint: '+12017777777', + }, + conferenceId: 'myConferenceId-E2E', + locale: 'en-US', + greeting: 'Welcome to this conference call.', + mohClass: 'music1', + }, + }, + }); +}); + +Then('the callout response contains the Conference call ID', () => { + assert.equal(ttsCallResponse.callId, '1ce0ffee-ca11-ca11-ca11-abcdef000002'); +}); + +When('I send a request to make a Custom call', async () => { + ttsCallResponse = await calloutsApi.custom({ + customCalloutRequestBody: { + method: 'customCallout', + customCallout: { + cli: '+12015555555', + destination: { + type: 'number', + endpoint: '+12017777777', + }, + custom: 'Custom text', + ice: Voice.customCalloutHelper.formatIceResponse( + Voice.iceActionHelper.connectPstn({ + number: '+12017777777', + cli: '+12015555555', + }), + Voice.iceInstructionHelper.say('Welcome to Sinch.', 'en-US/male'), + Voice.iceInstructionHelper.startRecording({ + destinationUrl: 'To specify', + credentials: 'To specify', + }), + ), + ace: Voice.customCalloutHelper.formatAceResponse( + Voice.aceActionHelper.runMenu({ + locale: 'Kimberly', + enableVoice: true, + barge: true, + menus: [ + { + id: 'main', + mainPrompt: '#tts[Welcome to the main menu. Press 1 to confirm order or 2 to cancel]', + repeatPrompt: '#tts[We didn\'t get your input, please try again]', + timeoutMills: 5000, + options: [ + { + dtmf: '1', + action: 'menu(confirm)', + }, + { + dtmf: '2', + action: 'return(cancel)', + }, + ], + }, + { + id: 'confirm', + mainPrompt: '#tts[Thank you for confirming your order. Enter your 4-digit PIN.]', + maxDigits: 4, + }, + ], + }), + ), + pie: 'https://callback-server.com/voice', + }, + }, + }); +}); + +Then('the callout response contains the Custom call ID', () => { + assert.equal(ttsCallResponse.callId, '1ce0ffee-ca11-ca11-ca11-abcdef000003'); +});