From 5f7921ffb27e5adc7ee1b6bd2d39d62cb8552db7 Mon Sep 17 00:00:00 2001 From: Pilli Vamshi Date: Wed, 4 Dec 2024 18:06:29 +0530 Subject: [PATCH 1/3] Added custom calling context in answer api. --- .../communication-call-automation/src/callAutomationClient.ts | 3 +++ .../communication-call-automation/src/models/options.ts | 2 ++ 2 files changed, 5 insertions(+) diff --git a/sdk/communication/communication-call-automation/src/callAutomationClient.ts b/sdk/communication/communication-call-automation/src/callAutomationClient.ts index e869021cdd24..4ddc27290eb6 100644 --- a/sdk/communication/communication-call-automation/src/callAutomationClient.ts +++ b/sdk/communication/communication-call-automation/src/callAutomationClient.ts @@ -334,6 +334,9 @@ export class CallAutomationClient { operationContext: operationContext, callbackUri: callbackUrl, answeredBy: this.sourceIdentity, + customCallingContext: this.createCustomCallingContextInternal( + options.customCallingContext!, + ), }; const optionsInternal = { ...operationOptions, diff --git a/sdk/communication/communication-call-automation/src/models/options.ts b/sdk/communication/communication-call-automation/src/models/options.ts index 17d23a535b70..3dbc9f0b8188 100644 --- a/sdk/communication/communication-call-automation/src/models/options.ts +++ b/sdk/communication/communication-call-automation/src/models/options.ts @@ -130,6 +130,8 @@ export interface AnswerCallOptions extends OperationOptions { transcriptionConfiguration?: TranscriptionConfiguration; /** The operation context. */ operationContext?: string; + /** The Custom Context. */ + customCallingContext?: CustomCallingContext; } /** From 11be23eb0bb906797bc2a365160e29fcaf2ef91a Mon Sep 17 00:00:00 2001 From: Pilli Vamshi Date: Thu, 5 Dec 2024 19:01:42 +0530 Subject: [PATCH 2/3] Added live and unit tests. --- .../node/callAutomationClient.live.spec.ts | 96 +++++++++++++++++++ .../test/node/callAutomationClient.spec.ts | 26 ++++- 2 files changed, 121 insertions(+), 1 deletion(-) diff --git a/sdk/communication/communication-call-automation/test/node/callAutomationClient.live.spec.ts b/sdk/communication/communication-call-automation/test/node/callAutomationClient.live.spec.ts index 6290834543f9..e1b673439088 100644 --- a/sdk/communication/communication-call-automation/test/node/callAutomationClient.live.spec.ts +++ b/sdk/communication/communication-call-automation/test/node/callAutomationClient.live.spec.ts @@ -112,6 +112,54 @@ describe("Call Automation Main Client Live Tests", { skip: !isNodeLike }, () => assert.isDefined(callDisconnectedEvent); }); + it("answer call with custom context and hangup", { timeout: 60000 }, async (ctx) => { + const fullTitle: string | undefined = + ctx.task.suite && ctx.task.suite.name && ctx.task.name + ? `${ctx.task.suite.name} ${ctx.task.name}` + : undefined; + + testName = fullTitle ? fullTitle.replace(/ /g, "_") : "answer_call_with_custom_context_and_hang_up"; + await loadPersistedEvents(testName); + + const callInvite: CallInvite = { targetParticipant: testUser2 }; + const uniqueId = await serviceBusWithNewCall(testUser, testUser2); + const callBackUrl: string = dispatcherCallback + `?q=${uniqueId}`; + const createCallOption: CreateCallOptions = { operationContext: "operationContextCreateCall" }; + + const result = await callerCallAutomationClient.createCall( + callInvite, + callBackUrl, + createCallOption, + ); + const incomingCallContext = await waitForIncomingCallContext(uniqueId, 8000); + const callConnectionId: string = result.callConnectionProperties.callConnectionId + ? result.callConnectionProperties.callConnectionId + : ""; + assert.isDefined(incomingCallContext); + + if (incomingCallContext) { + const answerCallOptions: AnswerCallOptions = { + operationContext: "operationContextAnswerCall", + customCallingContext : [{ kind: "voip", key: "foo", value: "bar" }] + }; + await receiverCallAutomationClient.answerCall( + incomingCallContext, + callBackUrl, + answerCallOptions, + ); + } + + const callConnectedEvent = await waitForEvent("CallConnected", callConnectionId, 8000); + + assert.isDefined(callConnectedEvent); + callConnection = result.callConnection; + + await callConnection.hangUp(true); + + const callDisconnectedEvent = await waitForEvent("CallDisconnected", callConnectionId, 8000); + assert.isDefined(callDisconnectedEvent); + }); + it("Reject call", { timeout: 60000 }, async (ctx) => { const fullTitle: string | undefined = ctx.task.suite && ctx.task.suite.name && ctx.task.name @@ -143,4 +191,52 @@ describe("Call Automation Main Client Live Tests", { skip: !isNodeLike }, () => const createCallFailedEvent = await waitForEvent("CreateCallFailed", callConnectionId, 8000); assert.isDefined(createCallFailedEvent); }); + + it("answer call with custom context and hangup", { timeout: 60000 }, async (ctx) => { + const fullTitle: string | undefined = + ctx.task.suite && ctx.task.suite.name && ctx.task.name + ? `${ctx.task.suite.name} ${ctx.task.name}` + : undefined; + + testName = fullTitle ? fullTitle.replace(/ /g, "_") : "create_call_and_hang_up"; + await loadPersistedEvents(testName); + + const callInvite: CallInvite = { targetParticipant: testUser2 }; + const uniqueId = await serviceBusWithNewCall(testUser, testUser2); + const callBackUrl: string = dispatcherCallback + `?q=${uniqueId}`; + const createCallOption: CreateCallOptions = { operationContext: "operationContextCreateCall" }; + + const result = await callerCallAutomationClient.createCall( + callInvite, + callBackUrl, + createCallOption, + ); + const incomingCallContext = await waitForIncomingCallContext(uniqueId, 8000); + const callConnectionId: string = result.callConnectionProperties.callConnectionId + ? result.callConnectionProperties.callConnectionId + : ""; + assert.isDefined(incomingCallContext); + + if (incomingCallContext) { + const answerCallOptions: AnswerCallOptions = { + operationContext: "operationContextAnswerCall", + customCallingContext = CustomCallingContextInternal[] + }; + await receiverCallAutomationClient.answerCall( + incomingCallContext, + callBackUrl, + answerCallOptions, + ); + } + + const callConnectedEvent = await waitForEvent("CallConnected", callConnectionId, 8000); + + assert.isDefined(callConnectedEvent); + callConnection = result.callConnection; + + await callConnection.hangUp(true); + + const callDisconnectedEvent = await waitForEvent("CallDisconnected", callConnectionId, 8000); + assert.isDefined(callDisconnectedEvent); + }); }); diff --git a/sdk/communication/communication-call-automation/test/node/callAutomationClient.spec.ts b/sdk/communication/communication-call-automation/test/node/callAutomationClient.spec.ts index bced07a5ff99..b53b4f67f51a 100644 --- a/sdk/communication/communication-call-automation/test/node/callAutomationClient.spec.ts +++ b/sdk/communication/communication-call-automation/test/node/callAutomationClient.spec.ts @@ -13,7 +13,7 @@ import type { CommunicationIdentifier, MicrosoftTeamsAppIdentifier, } from "@azure/communication-common"; -import type { CallInvite, CallConnection } from "../../src/index.js"; +import type { CallInvite, CallConnection, AnswerCallOptions } from "../../src/index.js"; import type { AnswerCallEventResult, CreateCallEventResult, @@ -198,6 +198,30 @@ describe("Call Automation Client Unit Tests", () => { assert.equal(result, answerCallResultMock); }); + it("AnswerCall with custom context", async () => { + // mocks + const answerCallResultMock: AnswerCallResult = { + callConnectionProperties: {} as CallConnectionProperties, + callConnection: {} as CallConnection, + waitForEventProcessor: async () => { + return {} as AnswerCallEventResult; + }, + }; + vi.spyOn(client, "answerCall").mockResolvedValue(answerCallResultMock); + const answerCallOptions: AnswerCallOptions = { + operationContext: "operationContextAnswerCall", + customCallingContext : [{ kind: "voip", key: "foo", value: "bar" }] + }; + const promiseResult = client.answerCall(CALL_INCOMING_CALL_CONTEXT, CALL_CALLBACK_URL, answerCallOptions); + + // asserts + const result = await promiseResult; + + assert.isNotNull(result); + expect(client.answerCall).toHaveBeenCalledWith(CALL_INCOMING_CALL_CONTEXT, CALL_CALLBACK_URL); + assert.equal(result, answerCallResultMock); + }); + it("RedirectCall", async () => { // mocks vi.spyOn(client, "redirectCall").mockReturnValue( From c9759759d0e01fd5aaf2bedddd106164855a2e7b Mon Sep 17 00:00:00 2001 From: Pilli Vamshi Date: Fri, 17 Jan 2025 17:59:44 +0530 Subject: [PATCH 3/3] Removed live test. --- .../node/callAutomationClient.live.spec.ts | 48 ------------------- 1 file changed, 48 deletions(-) diff --git a/sdk/communication/communication-call-automation/test/node/callAutomationClient.live.spec.ts b/sdk/communication/communication-call-automation/test/node/callAutomationClient.live.spec.ts index e1b673439088..a96e6c6feba2 100644 --- a/sdk/communication/communication-call-automation/test/node/callAutomationClient.live.spec.ts +++ b/sdk/communication/communication-call-automation/test/node/callAutomationClient.live.spec.ts @@ -191,52 +191,4 @@ describe("Call Automation Main Client Live Tests", { skip: !isNodeLike }, () => const createCallFailedEvent = await waitForEvent("CreateCallFailed", callConnectionId, 8000); assert.isDefined(createCallFailedEvent); }); - - it("answer call with custom context and hangup", { timeout: 60000 }, async (ctx) => { - const fullTitle: string | undefined = - ctx.task.suite && ctx.task.suite.name && ctx.task.name - ? `${ctx.task.suite.name} ${ctx.task.name}` - : undefined; - - testName = fullTitle ? fullTitle.replace(/ /g, "_") : "create_call_and_hang_up"; - await loadPersistedEvents(testName); - - const callInvite: CallInvite = { targetParticipant: testUser2 }; - const uniqueId = await serviceBusWithNewCall(testUser, testUser2); - const callBackUrl: string = dispatcherCallback + `?q=${uniqueId}`; - const createCallOption: CreateCallOptions = { operationContext: "operationContextCreateCall" }; - - const result = await callerCallAutomationClient.createCall( - callInvite, - callBackUrl, - createCallOption, - ); - const incomingCallContext = await waitForIncomingCallContext(uniqueId, 8000); - const callConnectionId: string = result.callConnectionProperties.callConnectionId - ? result.callConnectionProperties.callConnectionId - : ""; - assert.isDefined(incomingCallContext); - - if (incomingCallContext) { - const answerCallOptions: AnswerCallOptions = { - operationContext: "operationContextAnswerCall", - customCallingContext = CustomCallingContextInternal[] - }; - await receiverCallAutomationClient.answerCall( - incomingCallContext, - callBackUrl, - answerCallOptions, - ); - } - - const callConnectedEvent = await waitForEvent("CallConnected", callConnectionId, 8000); - - assert.isDefined(callConnectedEvent); - callConnection = result.callConnection; - - await callConnection.hangUp(true); - - const callDisconnectedEvent = await waitForEvent("CallDisconnected", callConnectionId, 8000); - assert.isDefined(callDisconnectedEvent); - }); });