Skip to content

Commit

Permalink
Add opt out client with methods, tests
Browse files Browse the repository at this point in the history
  • Loading branch information
phermanov-msft committed Nov 29, 2024
1 parent d5f44c7 commit b415604
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
```ts

import type { CommonClientOptions } from '@azure/core-client';
import * as coreClient from '@azure/core-client';
import type { KeyCredential } from '@azure/core-auth';
import type { OperationOptions } from '@azure/core-client';
import type { TokenCredential } from '@azure/core-auth';
Expand All @@ -14,6 +15,10 @@ export class SmsClient {
constructor(connectionString: string, options?: SmsClientOptions);
constructor(endpoint: string, credential: KeyCredential, options?: SmsClientOptions);
constructor(endpoint: string, credential: TokenCredential, options?: SmsClientOptions);
// Warning: (ae-forgotten-export) The symbol "OptOutsClient" needs to be exported by the entry point index.d.ts
//
// (undocumented)
optOuts: OptOutsClient;
send(sendRequest: SmsSendRequest, options?: SmsSendOptions): Promise<SmsSendResult[]>;
}

Expand Down
109 changes: 109 additions & 0 deletions sdk/communication/communication-sms/src/optOutsClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { tracingClient } from "./generated/src/tracing.js";
import type { OptOutResponseItem } from "./generated/src/index.js";
import type { SmsApiClient } from "./generated/src/smsApiClient.js";
import { generateOptOutRequest } from "./utils/smsUtils.js";
import { extractOperationOptions } from "./extractOperationOptions.js";
import type { OperationOptions } from "@azure/core-client";

export interface OptOutCheckResult {
to: string;
isOptedOut: boolean;
httpStatusCode: number;
errorMessage?: string;
}

export interface OptOutAddResult {
to: string;
httpStatusCode: number;
errorMessage?: string;
}

export interface OptOutRemoveResult {
to: string;
httpStatusCode: number;
errorMessage?: string;
}

export interface CheckOptions extends OperationOptions {
}

export interface AddOptions extends OperationOptions {
}

export interface RemoveOptions extends OperationOptions {
}

export class OptOutsClient {
private readonly api: SmsApiClient;

constructor(api: SmsApiClient) {
this.api = api;
}

public async remove( from: string,
to: string[],
options:RemoveOptions = {}): Promise<OptOutRemoveResult[]> {
const { operationOptions } = extractOperationOptions(options);
return tracingClient.withSpan("OptOuts-Remove", operationOptions, async (updatedOptions) => {
const response = await this.api.optOuts.add(
generateOptOutRequest(from, to),
updatedOptions,
);

return response.value.map((optOutResponseItem: OptOutResponseItem) => {
return {
to: optOutResponseItem.to,
httpStatusCode: optOutResponseItem.httpStatusCode,
errorMessage: optOutResponseItem.errorMessage ?? ""
};
});
});
}

public async add(
from: string,
to: string[],
options:AddOptions = {}): Promise<OptOutAddResult[]> {
const { operationOptions } = extractOperationOptions(options);
return tracingClient.withSpan("OptOuts-Add", operationOptions, async (updatedOptions) => {
const response = await this.api.optOuts.add(
generateOptOutRequest(from, to),
updatedOptions,
);

return response.value.map((optOutResponseItem: OptOutResponseItem) => {
return {
to: optOutResponseItem.to,
httpStatusCode: optOutResponseItem.httpStatusCode,
errorMessage: optOutResponseItem.errorMessage ?? ""
};
});
});
}

public async check(
from: string,
to: string[],
options:CheckOptions = {}
): Promise<OptOutCheckResult[]> {
const { operationOptions } = extractOperationOptions(options);
return tracingClient.withSpan("OptOuts-Check", operationOptions, async (updatedOptions) => {
const response = await this.api.optOuts.check(
generateOptOutRequest(from, to),
updatedOptions,
);

return response.value.map((optOutResponseItem: OptOutResponseItem) => {
return {
to: optOutResponseItem.to,
isOptedOut: optOutResponseItem.isOptedOut ?? false,
httpStatusCode: optOutResponseItem.httpStatusCode,
errorMessage: optOutResponseItem.errorMessage ?? ""
};
});
});
}
}
3 changes: 3 additions & 0 deletions sdk/communication/communication-sms/src/smsClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { extractOperationOptions } from "./extractOperationOptions.js";
import { generateSendMessageRequest } from "./utils/smsUtils.js";
import { logger } from "./logger.js";
import { tracingClient } from "./generated/src/tracing.js";
import { OptOutsClient } from "./optOutsClient.js";

/**
* Client options used to configure SMS Client API requests.
Expand Down Expand Up @@ -96,6 +97,7 @@ const isSmsClientOptions = (options: any): options is SmsClientOptions =>
*/
export class SmsClient {
private readonly api: SmsApiClient;
public optOuts: OptOutsClient;

/**
* Initializes a new instance of the SmsClient class.
Expand Down Expand Up @@ -141,6 +143,7 @@ export class SmsClient {
const authPolicy = createCommunicationAuthPolicy(credential);
this.api = new SmsApiClient(url, internalPipelineOptions);
this.api.pipeline.addPolicy(authPolicy);
this.optOuts = new OptOutsClient(this.api);
}

/**
Expand Down
14 changes: 13 additions & 1 deletion sdk/communication/communication-sms/src/utils/smsUtils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import type { SendMessageRequest } from "../generated/src/models/index.js";
import type { SendMessageRequest, OptOutRequest } from "../generated/src/models/index.js";
import type { SmsSendOptions, SmsSendRequest } from "../smsClient.js";
import { Uuid } from "./uuid.js";
import type { SmsSendOptions as InternalOptions } from "../generated/src/models/index.js";
Expand Down Expand Up @@ -33,3 +33,15 @@ export function generateSendMessageRequest(
},
};
}

export function generateOptOutRequest(
from: string,
to: string[]) : OptOutRequest {
return {
from: from,
recipients: to.map((phoneNumberStr) => {
return {
to: phoneNumberStr
};
})};
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,36 @@ matrix([[true, false]], async function (useAad: boolean) {
}
});
});

describe("Opt Outs Client", async () => {
it("OptOut Check must return as many results as there were recipients", { timeout: 4000 }, async () => {
const fromNumber = env.AZURE_PHONE_NUMBER as string;
const validToNumber = "+18335852071";
const results = await client.optOuts.check(fromNumber, [validToNumber]);

assert.lengthOf(results, 1, "must return as many results as there were recipients");
assert.equal(200, results[0].httpStatusCode);
});

it("OptOut Add must return as many results as there were recipients", { timeout: 4000 }, async () => {
const fromNumber = env.AZURE_PHONE_NUMBER as string;
const validToNumber = "+18335852071";
const results = await client.optOuts.add(fromNumber, [validToNumber]);

assert.lengthOf(results, 1, "must return as many results as there were recipients");
assert.equal(200, results[0].httpStatusCode);
});

it("OptOut Remove must return as many results as there were recipients", { timeout: 4000 }, async () => {
const fromNumber = env.AZURE_PHONE_NUMBER as string;
const validToNumber = "+18335852071";
const results = await client.optOuts.remove(fromNumber, [validToNumber]);

assert.lengthOf(results, 1, "must return as many results as there were recipients");
assert.equal(200, results[0].httpStatusCode);
});

});

});
});
31 changes: 31 additions & 0 deletions sdk/communication/communication-sms/test/public/smsClient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,37 @@ matrix([[true, false]], async function (useAad: boolean) {
assert.equal(e.statusCode, 401);
}
});

describe("Opt Outs Client", async () => {
it("OptOut Check must return as many results as there were recipients", { timeout: 4000 }, async () => {
const fromNumber = env.AZURE_PHONE_NUMBER as string;
const validToNumber = "+18335852071";
const results = await client.optOuts.check(fromNumber, [validToNumber]);

assert.lengthOf(results, 1, "must return as many results as there were recipients");
assert.equal(200, results[0].httpStatusCode);
});

it("OptOut Add must return as many results as there were recipients", { timeout: 4000 }, async () => {
const fromNumber = env.AZURE_PHONE_NUMBER as string;
const validToNumber = "+18335852071";
const results = await client.optOuts.add(fromNumber, [validToNumber]);

assert.lengthOf(results, 1, "must return as many results as there were recipients");
assert.equal(200, results[0].httpStatusCode);
});

it("OptOut Remove must return as many results as there were recipients", { timeout: 4000 }, async () => {
const fromNumber = env.AZURE_PHONE_NUMBER as string;
const validToNumber = "+18335852071";
const results = await client.optOuts.remove(fromNumber, [validToNumber]);

assert.lengthOf(results, 1, "must return as many results as there were recipients");
assert.equal(200, results[0].httpStatusCode);
});

});

});
},
);
Expand Down

0 comments on commit b415604

Please sign in to comment.