From fa62ae6a0a101378ff0dfda6d8f8ab0a96953035 Mon Sep 17 00:00:00 2001 From: Farhad Jabiyev Date: Thu, 7 Nov 2024 14:00:44 +0200 Subject: [PATCH 1/9] Run Autorest,Export-Api, implement new clients --- .../Azure.Communication.Sms.netstandard2.0.cs | 50 ++- .../Generated/CommunicationSmsModelFactory.cs | 37 +++ .../Models/OptOutRecipient.Serialization.cs | 31 ++ .../src/Generated/Models/OptOutRecipient.cs | 28 ++ .../Models/OptOutRequest.Serialization.cs | 38 +++ .../src/Generated/Models/OptOutRequest.cs | 44 +++ .../Models/OptOutResponse.Serialization.cs | 46 +++ .../src/Generated/Models/OptOutResponse.cs | 37 +++ .../OptOutResponseItem.Serialization.cs | 62 ++++ .../Generated/Models/OptOutResponseItem.cs | 49 +++ .../src/Generated/OptOutsRestClient.cs | 292 ++++++++++++++++++ .../src/Generated/SmsRestClient.cs | 2 +- .../src/Models/OptOutChangeResponse.cs | 33 ++ .../src/Models/OptOutChangeResponseItem.cs | 41 +++ .../src/Models/SendMessageRequest.cs | 12 - .../src/Models/SmsModelFactory.cs | 10 +- .../src/Models/SmsRecipient.cs | 12 - .../src/Models/SmsSendOptions.cs | 12 - .../src/Models/SmsSendResponse.cs | 12 - .../SmsSendResponseItemRepeatabilityResult.cs | 12 - .../src/OptOutsClient.cs | 219 +++++++++++++ .../Azure.Communication.Sms/src/SmsClient.cs | 7 + .../src/SmsClientOptions.cs | 6 +- .../Azure.Communication.Sms/src/autorest.md | 48 ++- 24 files changed, 1066 insertions(+), 74 deletions(-) create mode 100644 sdk/communication/Azure.Communication.Sms/src/Generated/CommunicationSmsModelFactory.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRecipient.Serialization.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRecipient.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRequest.Serialization.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRequest.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponse.Serialization.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponse.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponseItem.Serialization.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponseItem.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/Generated/OptOutsRestClient.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponse.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponseItem.cs delete mode 100644 sdk/communication/Azure.Communication.Sms/src/Models/SendMessageRequest.cs delete mode 100644 sdk/communication/Azure.Communication.Sms/src/Models/SmsRecipient.cs delete mode 100644 sdk/communication/Azure.Communication.Sms/src/Models/SmsSendOptions.cs delete mode 100644 sdk/communication/Azure.Communication.Sms/src/Models/SmsSendResponse.cs delete mode 100644 sdk/communication/Azure.Communication.Sms/src/Models/SmsSendResponseItemRepeatabilityResult.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs diff --git a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs index bf2d7f3d8a534..a92d13996fc00 100644 --- a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs +++ b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs @@ -1,5 +1,15 @@ namespace Azure.Communication.Sms { + public partial class OptOutsClient + { + protected OptOutsClient() { } + public virtual Azure.Response Add(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task> AddAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response Check(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task> CheckAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response Remove(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task> RemoveAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + } public partial class SmsClient { protected SmsClient() { } @@ -7,6 +17,7 @@ public SmsClient(string connectionString) { } public SmsClient(string connectionString, Azure.Communication.Sms.SmsClientOptions options) { } public SmsClient(System.Uri endpoint, Azure.AzureKeyCredential keyCredential, Azure.Communication.Sms.SmsClientOptions options = null) { } public SmsClient(System.Uri endpoint, Azure.Core.TokenCredential tokenCredential, Azure.Communication.Sms.SmsClientOptions options = null) { } + public virtual Azure.Communication.Sms.OptOutsClient OptOuts { get { throw null; } } public virtual Azure.Response> Send(string from, System.Collections.Generic.IEnumerable to, string message, Azure.Communication.Sms.SmsSendOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response Send(string from, string to, string message, Azure.Communication.Sms.SmsSendOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task>> SendAsync(string from, System.Collections.Generic.IEnumerable to, string message, Azure.Communication.Sms.SmsSendOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -14,11 +25,11 @@ public SmsClient(System.Uri endpoint, Azure.Core.TokenCredential tokenCredential } public partial class SmsClientOptions : Azure.Core.ClientOptions { - public SmsClientOptions(Azure.Communication.Sms.SmsClientOptions.ServiceVersion version = Azure.Communication.Sms.SmsClientOptions.ServiceVersion.V2024_02_05_Preview) { } + public SmsClientOptions(Azure.Communication.Sms.SmsClientOptions.ServiceVersion version = Azure.Communication.Sms.SmsClientOptions.ServiceVersion.V2024_12_10_Preview) { } public enum ServiceVersion { V2021_03_07 = 1, - V2024_02_05_Preview = 2, + V2024_12_10_Preview = 2, } } public partial class SmsSendOptions @@ -40,6 +51,41 @@ internal SmsSendResult() { } } namespace Azure.Communication.Sms.Models { + public static partial class CommunicationSmsModelFactory + { + public static Azure.Communication.Sms.Models.OptOutResponse OptOutResponse(System.Collections.Generic.IEnumerable value = null) { throw null; } + public static Azure.Communication.Sms.Models.OptOutResponseItem OptOutResponseItem(string to = null, int httpStatusCode = 0, bool? isOptedOut = default(bool?), string errorMessage = null) { throw null; } + } + public partial class OptOutChangeResponse + { + internal OptOutChangeResponse() { } + public System.Collections.Generic.IReadOnlyList Value { get { throw null; } } + } + public partial class OptOutChangeResponseItem + { + internal OptOutChangeResponseItem() { } + public string ErrorMessage { get { throw null; } } + public int HttpStatusCode { get { throw null; } } + public string To { get { throw null; } } + } + public partial class OptOutRecipient + { + public OptOutRecipient(string to) { } + public string To { get { throw null; } } + } + public partial class OptOutResponse + { + internal OptOutResponse() { } + public System.Collections.Generic.IReadOnlyList Value { get { throw null; } } + } + public partial class OptOutResponseItem + { + internal OptOutResponseItem() { } + public string ErrorMessage { get { throw null; } } + public int HttpStatusCode { get { throw null; } } + public bool? IsOptedOut { get { throw null; } } + public string To { get { throw null; } } + } public static partial class SmsModelFactory { public static Azure.Communication.Sms.SmsSendResult SmsSendResult(string to, string messageId, int httpStatusCode, bool successful, string errorMessage) { throw null; } diff --git a/sdk/communication/Azure.Communication.Sms/src/Generated/CommunicationSmsModelFactory.cs b/sdk/communication/Azure.Communication.Sms/src/Generated/CommunicationSmsModelFactory.cs new file mode 100644 index 0000000000000..47b7db0b5e56a --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Generated/CommunicationSmsModelFactory.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Communication.Sms.Models +{ + /// Model factory for models. + public static partial class CommunicationSmsModelFactory + { + /// Initializes a new instance of . + /// + /// A new instance for mocking. + public static OptOutResponse OptOutResponse(IEnumerable value = null) + { + value ??= new List(); + + return new OptOutResponse(value?.ToList()); + } + + /// Initializes a new instance of . + /// The recipient phone number (in E.164 format). + /// + /// Optional flag specifying if number was Opted Out from receiving messages. + /// Optional error message in case of 4xx/5xx errors. + /// A new instance for mocking. + public static OptOutResponseItem OptOutResponseItem(string to = null, int httpStatusCode = default, bool? isOptedOut = null, string errorMessage = null) + { + return new OptOutResponseItem(to, httpStatusCode, isOptedOut, errorMessage); + } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRecipient.Serialization.cs b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRecipient.Serialization.cs new file mode 100644 index 0000000000000..3b1dec2b691af --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRecipient.Serialization.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Communication.Sms.Models +{ + public partial class OptOutRecipient : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + writer.WritePropertyName("to"u8); + writer.WriteStringValue(To); + writer.WriteEndObject(); + } + + /// Convert into a . + internal virtual RequestContent ToRequestContent() + { + var content = new Utf8JsonRequestContent(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRecipient.cs b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRecipient.cs new file mode 100644 index 0000000000000..a634e45e0e052 --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRecipient.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Communication.Sms.Models +{ + /// A single opt out recipient number. + public partial class OptOutRecipient + { + /// Initializes a new instance of . + /// The recipient's phone number (in E.164 format). + /// is null. + public OptOutRecipient(string to) + { + Argument.AssertNotNull(to, nameof(to)); + + To = to; + } + + /// The recipient's phone number (in E.164 format). + public string To { get; } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRequest.Serialization.cs b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRequest.Serialization.cs new file mode 100644 index 0000000000000..3cb93c1ded7ae --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRequest.Serialization.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Communication.Sms.Models +{ + internal partial class OptOutRequest : IUtf8JsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) + { + writer.WriteStartObject(); + writer.WritePropertyName("from"u8); + writer.WriteStringValue(From); + writer.WritePropertyName("recipients"u8); + writer.WriteStartArray(); + foreach (var item in Recipients) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WriteEndObject(); + } + + /// Convert into a . + internal virtual RequestContent ToRequestContent() + { + var content = new Utf8JsonRequestContent(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRequest.cs b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRequest.cs new file mode 100644 index 0000000000000..8296be4b36b4e --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutRequest.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Communication.Sms.Models +{ + /// An opt out request. + internal partial class OptOutRequest + { + /// Initializes a new instance of . + /// The sender's identifier (typically phone number in E.164 format) that is owned by the authenticated account. + /// + /// or is null. + public OptOutRequest(string @from, IEnumerable recipients) + { + Argument.AssertNotNull(@from, nameof(@from)); + Argument.AssertNotNull(recipients, nameof(recipients)); + + From = @from; + Recipients = recipients.ToList(); + } + + /// Initializes a new instance of . + /// The sender's identifier (typically phone number in E.164 format) that is owned by the authenticated account. + /// + internal OptOutRequest(string @from, IList recipients) + { + From = @from; + Recipients = recipients; + } + + /// The sender's identifier (typically phone number in E.164 format) that is owned by the authenticated account. + public string From { get; } + /// Gets the recipients. + public IList Recipients { get; } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponse.Serialization.cs b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponse.Serialization.cs new file mode 100644 index 0000000000000..1bca57f4492b9 --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponse.Serialization.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; + +namespace Azure.Communication.Sms.Models +{ + public partial class OptOutResponse + { + internal static OptOutResponse DeserializeOptOutResponse(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + IReadOnlyList value = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("value"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(OptOutResponseItem.DeserializeOptOutResponseItem(item)); + } + value = array; + continue; + } + } + return new OptOutResponse(value); + } + + /// Deserializes the model from a raw response. + /// The response to deserialize the model from. + internal static OptOutResponse FromResponse(Response response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeOptOutResponse(document.RootElement); + } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponse.cs b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponse.cs new file mode 100644 index 0000000000000..506a7dba86156 --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponse.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Communication.Sms.Models +{ + /// Response for an opt out request. Validate the returned items in the response to see which recipients were successfully added or removed from the opt outs list. + public partial class OptOutResponse + { + /// Initializes a new instance of . + /// + /// is null. + internal OptOutResponse(IEnumerable value) + { + Argument.AssertNotNull(value, nameof(value)); + + Value = value.ToList(); + } + + /// Initializes a new instance of . + /// + internal OptOutResponse(IReadOnlyList value) + { + Value = value; + } + + /// Gets the value. + public IReadOnlyList Value { get; } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponseItem.Serialization.cs b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponseItem.Serialization.cs new file mode 100644 index 0000000000000..d3e553550187a --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponseItem.Serialization.cs @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; + +namespace Azure.Communication.Sms.Models +{ + public partial class OptOutResponseItem + { + internal static OptOutResponseItem DeserializeOptOutResponseItem(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string to = default; + int httpStatusCode = default; + bool? isOptedOut = default; + string errorMessage = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("to"u8)) + { + to = property.Value.GetString(); + continue; + } + if (property.NameEquals("httpStatusCode"u8)) + { + httpStatusCode = property.Value.GetInt32(); + continue; + } + if (property.NameEquals("isOptedOut"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + isOptedOut = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("errorMessage"u8)) + { + errorMessage = property.Value.GetString(); + continue; + } + } + return new OptOutResponseItem(to, httpStatusCode, isOptedOut, errorMessage); + } + + /// Deserializes the model from a raw response. + /// The response to deserialize the model from. + internal static OptOutResponseItem FromResponse(Response response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeOptOutResponseItem(document.RootElement); + } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponseItem.cs b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponseItem.cs new file mode 100644 index 0000000000000..fddd37370ae6d --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Generated/Models/OptOutResponseItem.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Communication.Sms.Models +{ + /// The OptOutResponseItem. + public partial class OptOutResponseItem + { + /// Initializes a new instance of . + /// The recipient phone number (in E.164 format). + /// + /// is null. + internal OptOutResponseItem(string to, int httpStatusCode) + { + Argument.AssertNotNull(to, nameof(to)); + + To = to; + HttpStatusCode = httpStatusCode; + } + + /// Initializes a new instance of . + /// The recipient phone number (in E.164 format). + /// + /// Optional flag specifying if number was Opted Out from receiving messages. + /// Optional error message in case of 4xx/5xx errors. + internal OptOutResponseItem(string to, int httpStatusCode, bool? isOptedOut, string errorMessage) + { + To = to; + HttpStatusCode = httpStatusCode; + IsOptedOut = isOptedOut; + ErrorMessage = errorMessage; + } + + /// The recipient phone number (in E.164 format). + public string To { get; } + /// Gets the http status code. + public int HttpStatusCode { get; } + /// Optional flag specifying if number was Opted Out from receiving messages. + public bool? IsOptedOut { get; } + /// Optional error message in case of 4xx/5xx errors. + public string ErrorMessage { get; } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Generated/OptOutsRestClient.cs b/sdk/communication/Azure.Communication.Sms/src/Generated/OptOutsRestClient.cs new file mode 100644 index 0000000000000..d01c7ab48ef44 --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Generated/OptOutsRestClient.cs @@ -0,0 +1,292 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Azure.Communication.Sms.Models; +using Azure.Core; +using Azure.Core.Pipeline; + +namespace Azure.Communication.Sms +{ + internal partial class OptOutsRestClient + { + private readonly HttpPipeline _pipeline; + private readonly Uri _endpoint; + private readonly string _apiVersion; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal ClientDiagnostics ClientDiagnostics { get; } + + /// Initializes a new instance of OptOutsRestClient. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The communication resource, for example https://my-resource.communication.azure.com. + /// Api Version. + /// , , or is null. + public OptOutsRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, Uri endpoint, string apiVersion = "2024-12-10-preview") + { + ClientDiagnostics = clientDiagnostics ?? throw new ArgumentNullException(nameof(clientDiagnostics)); + _pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); + _endpoint = endpoint ?? throw new ArgumentNullException(nameof(endpoint)); + _apiVersion = apiVersion ?? throw new ArgumentNullException(nameof(apiVersion)); + } + + internal HttpMessage CreateAddRequest(string @from, IEnumerable recipients) + { + var message = _pipeline.CreateMessage(); + var request = message.Request; + request.Method = RequestMethod.Post; + var uri = new RawRequestUriBuilder(); + uri.Reset(_endpoint); + uri.AppendPath("/sms/optouts:add", false); + uri.AppendQuery("api-version", _apiVersion, true); + request.Uri = uri; + request.Headers.Add("Accept", "application/json"); + request.Headers.Add("Content-Type", "application/json"); + var model = new OptOutRequest(@from, recipients.ToList()); + var content = new Utf8JsonRequestContent(); + content.JsonWriter.WriteObjectValue(model); + request.Content = content; + return message; + } + + /// Add phone numbers to the optouts list which shall stop receiving messages from a sender number. + /// The sender's identifier (typically phone number in E.164 format) that is owned by the authenticated account. + /// The where T is of type to use. + /// The cancellation token to use. + /// or is null. + public async Task> AddAsync(string @from, IEnumerable recipients, CancellationToken cancellationToken = default) + { + if (@from == null) + { + throw new ArgumentNullException(nameof(@from)); + } + if (recipients == null) + { + throw new ArgumentNullException(nameof(recipients)); + } + + using var message = CreateAddRequest(@from, recipients); + await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); + switch (message.Response.Status) + { + case 200: + { + OptOutResponse value = default; + using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); + value = OptOutResponse.DeserializeOptOutResponse(document.RootElement); + return Response.FromValue(value, message.Response); + } + default: + throw new RequestFailedException(message.Response); + } + } + + /// Add phone numbers to the optouts list which shall stop receiving messages from a sender number. + /// The sender's identifier (typically phone number in E.164 format) that is owned by the authenticated account. + /// The where T is of type to use. + /// The cancellation token to use. + /// or is null. + public Response Add(string @from, IEnumerable recipients, CancellationToken cancellationToken = default) + { + if (@from == null) + { + throw new ArgumentNullException(nameof(@from)); + } + if (recipients == null) + { + throw new ArgumentNullException(nameof(recipients)); + } + + using var message = CreateAddRequest(@from, recipients); + _pipeline.Send(message, cancellationToken); + switch (message.Response.Status) + { + case 200: + { + OptOutResponse value = default; + using var document = JsonDocument.Parse(message.Response.ContentStream); + value = OptOutResponse.DeserializeOptOutResponse(document.RootElement); + return Response.FromValue(value, message.Response); + } + default: + throw new RequestFailedException(message.Response); + } + } + + internal HttpMessage CreateRemoveRequest(string @from, IEnumerable recipients) + { + var message = _pipeline.CreateMessage(); + var request = message.Request; + request.Method = RequestMethod.Post; + var uri = new RawRequestUriBuilder(); + uri.Reset(_endpoint); + uri.AppendPath("/sms/optouts:remove", false); + uri.AppendQuery("api-version", _apiVersion, true); + request.Uri = uri; + request.Headers.Add("Accept", "application/json"); + request.Headers.Add("Content-Type", "application/json"); + var model = new OptOutRequest(@from, recipients.ToList()); + var content = new Utf8JsonRequestContent(); + content.JsonWriter.WriteObjectValue(model); + request.Content = content; + return message; + } + + /// Remove phone numbers from the optouts list. + /// The sender's identifier (typically phone number in E.164 format) that is owned by the authenticated account. + /// The where T is of type to use. + /// The cancellation token to use. + /// or is null. + public async Task> RemoveAsync(string @from, IEnumerable recipients, CancellationToken cancellationToken = default) + { + if (@from == null) + { + throw new ArgumentNullException(nameof(@from)); + } + if (recipients == null) + { + throw new ArgumentNullException(nameof(recipients)); + } + + using var message = CreateRemoveRequest(@from, recipients); + await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); + switch (message.Response.Status) + { + case 200: + { + OptOutResponse value = default; + using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); + value = OptOutResponse.DeserializeOptOutResponse(document.RootElement); + return Response.FromValue(value, message.Response); + } + default: + throw new RequestFailedException(message.Response); + } + } + + /// Remove phone numbers from the optouts list. + /// The sender's identifier (typically phone number in E.164 format) that is owned by the authenticated account. + /// The where T is of type to use. + /// The cancellation token to use. + /// or is null. + public Response Remove(string @from, IEnumerable recipients, CancellationToken cancellationToken = default) + { + if (@from == null) + { + throw new ArgumentNullException(nameof(@from)); + } + if (recipients == null) + { + throw new ArgumentNullException(nameof(recipients)); + } + + using var message = CreateRemoveRequest(@from, recipients); + _pipeline.Send(message, cancellationToken); + switch (message.Response.Status) + { + case 200: + { + OptOutResponse value = default; + using var document = JsonDocument.Parse(message.Response.ContentStream); + value = OptOutResponse.DeserializeOptOutResponse(document.RootElement); + return Response.FromValue(value, message.Response); + } + default: + throw new RequestFailedException(message.Response); + } + } + + internal HttpMessage CreateCheckRequest(string @from, IEnumerable recipients) + { + var message = _pipeline.CreateMessage(); + var request = message.Request; + request.Method = RequestMethod.Post; + var uri = new RawRequestUriBuilder(); + uri.Reset(_endpoint); + uri.AppendPath("/sms/optouts:check", false); + uri.AppendQuery("api-version", _apiVersion, true); + request.Uri = uri; + request.Headers.Add("Accept", "application/json"); + request.Headers.Add("Content-Type", "application/json"); + var model = new OptOutRequest(@from, recipients.ToList()); + var content = new Utf8JsonRequestContent(); + content.JsonWriter.WriteObjectValue(model); + request.Content = content; + return message; + } + + /// Check the opt out status for a recipient phone number with a sender phone number. + /// The sender's identifier (typically phone number in E.164 format) that is owned by the authenticated account. + /// The where T is of type to use. + /// The cancellation token to use. + /// or is null. + public async Task> CheckAsync(string @from, IEnumerable recipients, CancellationToken cancellationToken = default) + { + if (@from == null) + { + throw new ArgumentNullException(nameof(@from)); + } + if (recipients == null) + { + throw new ArgumentNullException(nameof(recipients)); + } + + using var message = CreateCheckRequest(@from, recipients); + await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); + switch (message.Response.Status) + { + case 200: + { + OptOutResponse value = default; + using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); + value = OptOutResponse.DeserializeOptOutResponse(document.RootElement); + return Response.FromValue(value, message.Response); + } + default: + throw new RequestFailedException(message.Response); + } + } + + /// Check the opt out status for a recipient phone number with a sender phone number. + /// The sender's identifier (typically phone number in E.164 format) that is owned by the authenticated account. + /// The where T is of type to use. + /// The cancellation token to use. + /// or is null. + public Response Check(string @from, IEnumerable recipients, CancellationToken cancellationToken = default) + { + if (@from == null) + { + throw new ArgumentNullException(nameof(@from)); + } + if (recipients == null) + { + throw new ArgumentNullException(nameof(recipients)); + } + + using var message = CreateCheckRequest(@from, recipients); + _pipeline.Send(message, cancellationToken); + switch (message.Response.Status) + { + case 200: + { + OptOutResponse value = default; + using var document = JsonDocument.Parse(message.Response.ContentStream); + value = OptOutResponse.DeserializeOptOutResponse(document.RootElement); + return Response.FromValue(value, message.Response); + } + default: + throw new RequestFailedException(message.Response); + } + } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Generated/SmsRestClient.cs b/sdk/communication/Azure.Communication.Sms/src/Generated/SmsRestClient.cs index 75cba1514cbfa..4fd79b83b6e4e 100644 --- a/sdk/communication/Azure.Communication.Sms/src/Generated/SmsRestClient.cs +++ b/sdk/communication/Azure.Communication.Sms/src/Generated/SmsRestClient.cs @@ -32,7 +32,7 @@ internal partial class SmsRestClient /// The communication resource, for example https://my-resource.communication.azure.com. /// Api Version. /// , , or is null. - public SmsRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, Uri endpoint, string apiVersion = "2024-02-05-preview") + public SmsRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, Uri endpoint, string apiVersion = "2024-12-10-preview") { ClientDiagnostics = clientDiagnostics ?? throw new ArgumentNullException(nameof(clientDiagnostics)); _pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline)); diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponse.cs b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponse.cs new file mode 100644 index 0000000000000..38b02296c11c8 --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponse.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Communication.Sms.Models +{ + /// Response for an opt out request. Validate the returned items in the response to see which recipients were successfully added or removed from the opt outs list. + public partial class OptOutChangeResponse + { + /// Initializes a new instance of . + /// + /// is null. + internal OptOutChangeResponse(IEnumerable value) + { + Argument.AssertNotNull(value, nameof(value)); + + Value = value.ToList(); + } + + /// Initializes a new instance of . + /// + internal OptOutChangeResponse(IReadOnlyList value) + { + Value = value; + } + + /// Gets the value. + public IReadOnlyList Value { get; } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponseItem.cs b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponseItem.cs new file mode 100644 index 0000000000000..48e380b15273a --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponseItem.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.Communication.Sms.Models +{ + /// The OptOutChangeResponseItem. + public class OptOutChangeResponseItem + { + /// Initializes a new instance of . + /// The recipient phone number (in E.164 format). + /// + /// is null. + internal OptOutChangeResponseItem(string to, int httpStatusCode) + { + Argument.AssertNotNull(to, nameof(to)); + + To = to; + HttpStatusCode = httpStatusCode; + } + + /// Initializes a new instance of . + /// The recipient phone number (in E.164 format). + /// + /// Optional error message in case of 4xx/5xx errors. + internal OptOutChangeResponseItem(string to, int httpStatusCode, string errorMessage) + { + To = to; + HttpStatusCode = httpStatusCode; + ErrorMessage = errorMessage; + } + + /// The recipient phone number (in E.164 format). + public string To { get; } + /// Gets the http status code. + public int HttpStatusCode { get; } + /// Optional error message in case of 4xx/5xx errors. + public string ErrorMessage { get; } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/SendMessageRequest.cs b/sdk/communication/Azure.Communication.Sms/src/Models/SendMessageRequest.cs deleted file mode 100644 index 34573bc0722c3..0000000000000 --- a/sdk/communication/Azure.Communication.Sms/src/Models/SendMessageRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Azure.Core; - -namespace Azure.Communication.Sms.Models -{ - [CodeGenModel("SendMessageRequest")] - internal partial class SendMessageRequest - { - } -} diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/SmsModelFactory.cs b/sdk/communication/Azure.Communication.Sms/src/Models/SmsModelFactory.cs index 972e4fd3289d8..6529eadf5fee6 100644 --- a/sdk/communication/Azure.Communication.Sms/src/Models/SmsModelFactory.cs +++ b/sdk/communication/Azure.Communication.Sms/src/Models/SmsModelFactory.cs @@ -1,12 +1,12 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +#nullable disable + namespace Azure.Communication.Sms.Models { - /// - /// Model factory that enables mocking for the Sms library. - /// - public static class SmsModelFactory + /// Model factory for models. + public static partial class SmsModelFactory { /// Initializes a new instance of SmsSendResult. /// The recipient's phone number in E.164 format. diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/SmsRecipient.cs b/sdk/communication/Azure.Communication.Sms/src/Models/SmsRecipient.cs deleted file mode 100644 index 743cd3356039e..0000000000000 --- a/sdk/communication/Azure.Communication.Sms/src/Models/SmsRecipient.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Azure.Core; - -namespace Azure.Communication.Sms.Models -{ - [CodeGenModel("SmsRecipient")] - internal partial class SmsRecipient - { - } -} diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/SmsSendOptions.cs b/sdk/communication/Azure.Communication.Sms/src/Models/SmsSendOptions.cs deleted file mode 100644 index 2adebb86aad38..0000000000000 --- a/sdk/communication/Azure.Communication.Sms/src/Models/SmsSendOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Azure.Core; - -namespace Azure.Communication.Sms -{ - [CodeGenModel("SmsSendOptions")] - public partial class SmsSendOptions - { - } -} diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/SmsSendResponse.cs b/sdk/communication/Azure.Communication.Sms/src/Models/SmsSendResponse.cs deleted file mode 100644 index 8c01d4e461c1a..0000000000000 --- a/sdk/communication/Azure.Communication.Sms/src/Models/SmsSendResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Azure.Core; - -namespace Azure.Communication.Sms.Models -{ - [CodeGenModel("SmsSendResponse")] - internal partial class SmsSendResponse - { - } -} diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/SmsSendResponseItemRepeatabilityResult.cs b/sdk/communication/Azure.Communication.Sms/src/Models/SmsSendResponseItemRepeatabilityResult.cs deleted file mode 100644 index 3033fab011e5e..0000000000000 --- a/sdk/communication/Azure.Communication.Sms/src/Models/SmsSendResponseItemRepeatabilityResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Azure.Core; - -namespace Azure.Communication.Sms -{ - [CodeGenModel("SmsSendResponseItemRepeatabilityResult")] - internal readonly partial struct SmsSendResponseItemRepeatabilityResult - { - } -} diff --git a/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs b/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs new file mode 100644 index 0000000000000..871e82be385ac --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs @@ -0,0 +1,219 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Communication.Sms.Models; +using Azure.Core.Pipeline; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Threading; +using System; +using System.Linq; + +namespace Azure.Communication.Sms +{ + /// + /// The Azure Communication Services SMS Opt Out Management client. + /// + public class OptOutsClient + { + private readonly ClientDiagnostics _clientDiagnostics; + + internal OptOutsRestClient OptOutsRestClient; + + internal OptOutsClient(OptOutsRestClient optOutsRestClient, ClientDiagnostics clientDiagnostics) + { + OptOutsRestClient = optOutsRestClient; + _clientDiagnostics = clientDiagnostics; + } + + /// Initializes a new instance of for mocking. + protected OptOutsClient() + { + _clientDiagnostics = null; + OptOutsRestClient = null; + } + + /// + /// Checks if phone numbers are opted out from phone number. + /// + /// The sender's phone number that is owned by the authenticated account. + /// The recipient's phone number. + /// The cancellation token for the task. + /// The server returned an error. See for details returned from the server. + /// is null. + /// is null. + public virtual async Task> CheckAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(SmsClient)}.{nameof(OptOutsClient)}.{nameof(CheckAsync)}"); + scope.Start(); + try + { + Argument.AssertNotNullOrEmpty(from, nameof(from)); + Argument.AssertNotNullOrEmpty(to, nameof(to)); + IEnumerable recipients = to.Select(x => new OptOutRecipient(Argument.CheckNotNullOrEmpty(x, nameof(to)))); + + Response response = await OptOutsRestClient.CheckAsync(from, recipients, cancellationToken).ConfigureAwait(false); + return Response.FromValue(response.Value, response.GetRawResponse()); + } + catch (Exception ex) + { + scope.Failed(ex); + throw; + } + } + + /// + /// Checks if phone numbers are opted out from phone number. + /// + /// The sender's phone number that is owned by the authenticated account. + /// The recipient's phone number. + /// The cancellation token for the task. + /// The server returned an error. See for details returned from the server. + /// is null. + /// is null. + public virtual Response Check(string from, IEnumerable to, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(SmsClient)}.{nameof(OptOutsClient)}.{nameof(Check)}"); + scope.Start(); + try + { + Argument.AssertNotNullOrEmpty(from, nameof(from)); + Argument.AssertNotNullOrEmpty(to, nameof(to)); + + IEnumerable recipients = to.Select(x => new OptOutRecipient(Argument.CheckNotNullOrEmpty(x, nameof(to)))); + + Response response = OptOutsRestClient.Check(from, recipients, cancellationToken); + return Response.FromValue(response.Value, response.GetRawResponse()); + } + catch (Exception ex) + { + scope.Failed(ex); + throw; + } + } + + /// + /// Opts out phone numbers from receiving SMS from phone number. + /// + /// The sender's phone number that is owned by the authenticated account. + /// The recipient's phone number which should be opted out. + /// The cancellation token for the task. + /// The server returned an error. See for details returned from the server. + /// is null. + /// is null. + public virtual async Task> AddAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(SmsClient)}.{nameof(OptOutsClient)}.{nameof(AddAsync)}"); + scope.Start(); + try + { + Argument.AssertNotNullOrEmpty(from, nameof(from)); + Argument.AssertNotNullOrEmpty(to, nameof(to)); + IEnumerable recipients = to.Select(x => new OptOutRecipient(Argument.CheckNotNullOrEmpty(x, nameof(to)))); + + Response response = await OptOutsRestClient.AddAsync(from, recipients, cancellationToken).ConfigureAwait(false); + OptOutChangeResponse result = new OptOutChangeResponse(response.Value.Value.Select(r => new OptOutChangeResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); + + return Response.FromValue(result, response.GetRawResponse()); + } + catch (Exception ex) + { + scope.Failed(ex); + throw; + } + } + + /// + /// Opts out phone numbers from receiving SMS from phone number. + /// + /// The sender's phone number that is owned by the authenticated account. + /// The recipient's phone number which should be opted out. + /// The cancellation token for the task. + /// The server returned an error. See for details returned from the server. + /// is null. + /// is null. + public virtual Response Add(string from, IEnumerable to, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(SmsClient)}.{nameof(OptOutsClient)}.{nameof(Add)}"); + scope.Start(); + try + { + Argument.AssertNotNullOrEmpty(from, nameof(from)); + Argument.AssertNotNullOrEmpty(to, nameof(to)); + + IEnumerable recipients = to.Select(x => new OptOutRecipient(Argument.CheckNotNullOrEmpty(x, nameof(to)))); + Response response = OptOutsRestClient.Add(from, recipients, cancellationToken); + OptOutChangeResponse result = new OptOutChangeResponse(response.Value.Value.Select(r => new OptOutChangeResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); + + return Response.FromValue(result, response.GetRawResponse()); + } + catch (Exception ex) + { + scope.Failed(ex); + throw; + } + } + + /// + /// Opts in phone numbers to receive SMS from phone number. + /// + /// The sender's phone number that is owned by the authenticated account. + /// The recipient's phone number which should be opted in. + /// The cancellation token for the task. + /// The server returned an error. See for details returned from the server. + /// is null. + /// is null. + public virtual async Task> RemoveAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(SmsClient)}.{nameof(OptOutsClient)}.{nameof(RemoveAsync)}"); + scope.Start(); + try + { + Argument.AssertNotNullOrEmpty(from, nameof(from)); + Argument.AssertNotNullOrEmpty(to, nameof(to)); + IEnumerable recipients = to.Select(x => new OptOutRecipient(Argument.CheckNotNullOrEmpty(x, nameof(to)))); + + Response response = await OptOutsRestClient.RemoveAsync(from, recipients, cancellationToken).ConfigureAwait(false); + OptOutChangeResponse result = new OptOutChangeResponse(response.Value.Value.Select(r => new OptOutChangeResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); + + return Response.FromValue(result, response.GetRawResponse()); + } + catch (Exception ex) + { + scope.Failed(ex); + throw; + } + } + + /// + /// Opts in phone numbers to receive SMS from phone number. + /// + /// The sender's phone number that is owned by the authenticated account. + /// The recipient's phone number which should be opted in. + /// The cancellation token for the task. + /// The server returned an error. See for details returned from the server. + /// is null. + /// is null. + public virtual Response Remove(string from, IEnumerable to, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(SmsClient)}.{nameof(OptOutsClient)}.{nameof(Remove)}"); + scope.Start(); + try + { + Argument.AssertNotNullOrEmpty(from, nameof(from)); + Argument.AssertNotNullOrEmpty(to, nameof(to)); + + IEnumerable recipients = to.Select(x => new OptOutRecipient(Argument.CheckNotNullOrEmpty(x, nameof(to)))); + Response response = OptOutsRestClient.Remove(from, recipients, cancellationToken); + OptOutChangeResponse result = new OptOutChangeResponse(response.Value.Value.Select(r => new OptOutChangeResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); + + return Response.FromValue(result, response.GetRawResponse()); + } + catch (Exception ex) + { + scope.Failed(ex); + throw; + } + } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/SmsClient.cs b/sdk/communication/Azure.Communication.Sms/src/SmsClient.cs index 2e31c17d39a8d..7c9a2a9832881 100644 --- a/sdk/communication/Azure.Communication.Sms/src/SmsClient.cs +++ b/sdk/communication/Azure.Communication.Sms/src/SmsClient.cs @@ -83,6 +83,7 @@ private SmsClient(string endpoint, HttpPipeline httpPipeline, SmsClientOptions o { _clientDiagnostics = new ClientDiagnostics(options); RestClient = new SmsRestClient(_clientDiagnostics, httpPipeline, new Uri(endpoint), options.ApiVersion); + OptOuts = new OptOutsClient(new OptOutsRestClient(_clientDiagnostics, httpPipeline, new Uri(endpoint), options.ApiVersion), _clientDiagnostics); } #endregion @@ -92,8 +93,14 @@ protected SmsClient() { _clientDiagnostics = null; RestClient = null; + OptOuts = null; } + /// + /// Opt Out management client. + /// + public virtual OptOutsClient OptOuts { get; private set; } + /// /// Sends a SMS a phone number that is acquired by the authenticated account, another phone number. /// diff --git a/sdk/communication/Azure.Communication.Sms/src/SmsClientOptions.cs b/sdk/communication/Azure.Communication.Sms/src/SmsClientOptions.cs index 84201c3641613..d76b0536f99f2 100644 --- a/sdk/communication/Azure.Communication.Sms/src/SmsClientOptions.cs +++ b/sdk/communication/Azure.Communication.Sms/src/SmsClientOptions.cs @@ -14,7 +14,7 @@ public class SmsClientOptions : ClientOptions /// /// The latest version of the Sms service. /// - private const ServiceVersion LatestVersion = ServiceVersion.V2024_02_05_Preview; + private const ServiceVersion LatestVersion = ServiceVersion.V2024_12_10_Preview; internal string ApiVersion { get; } @@ -26,7 +26,7 @@ public SmsClientOptions(ServiceVersion version = LatestVersion) ApiVersion = version switch { ServiceVersion.V2021_03_07 => "2021-03-07", - ServiceVersion.V2024_02_05_Preview => "2024-02-05-preview", + ServiceVersion.V2024_12_10_Preview => "2024-12-10-preview", _ => throw new ArgumentOutOfRangeException(nameof(version)), }; } @@ -44,7 +44,7 @@ public enum ServiceVersion /// /// The "2024-02-05-preview" of the Sms service. /// - V2024_02_05_Preview = 2 + V2024_12_10_Preview = 2 #pragma warning restore CA1707 // Identifiers should not contain underscores } } diff --git a/sdk/communication/Azure.Communication.Sms/src/autorest.md b/sdk/communication/Azure.Communication.Sms/src/autorest.md index f43a4079385ed..ec53a5658606c 100644 --- a/sdk/communication/Azure.Communication.Sms/src/autorest.md +++ b/sdk/communication/Azure.Communication.Sms/src/autorest.md @@ -6,10 +6,52 @@ Run `dotnet msbuild /t:GenerateCode` to generate code. > see https://aka.ms/autorest ``` yaml -tag: package-sms-2024-02-05-preview -model-namespace: false +tag: package-sms-2024-12-10-preview +model-namespace: true require: - - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/8df53db16935b96733fda9882c3f197e2f961287/specification/communication/data-plane/Sms/readme.md + - C:\azure-rest-api-specs\specification\communication\data-plane\Sms\readme.md payload-flattening-threshold: 10 generation1-convenience-client: true ``` + +``` yaml +directive: + from: swagger-document + where: "$.definitions.SmsSendResponseItem" + transform: > + $["x-ms-client-name"] = "SmsSendResult"; + $["x-namespace"] = "Azure.Communication.Sms"; +``` + +``` yaml +directive: + from: swagger-document + where: "$.definitions.SmsSendOptions" + transform: > + $["x-namespace"] = "Azure.Communication.Sms"; +``` + +``` yaml +directive: + from: swagger-document + where: "$.definitions.SmsRecipient" + transform: > + $["x-accessibility"] = "internal"; +``` + +``` yaml +directive: + from: swagger-document + where: "$.definitions.SmsSendResponse" + transform: > + $["x-accessibility"] = "internal"; +``` + +``` yaml +directive: + from: swagger-document + where: "$.definitions.SmsSendResponseItem.properties.repeatabilityResult" + transform: > + $["x-accessibility"] = "internal"; + $["x-namespace"] = "Azure.Communication.Sms"; +``` \ No newline at end of file From b5e3b86952106514edd20ffb0d2bd62321fbd3aa Mon Sep 17 00:00:00 2001 From: FarhadJabiyev Date: Sat, 9 Nov 2024 11:28:24 +0200 Subject: [PATCH 2/9] Add unit tests --- .../src/Models/SmsModelFactory.cs | 10 +- .../src/OptOutsClient.cs | 19 +- .../Azure.Communication.Sms/src/SmsClient.cs | 2 +- .../tests/OptOutsClientTest.cs | 198 +++++++++++++ .../tests/OptOutsRestClientTests.cs | 279 ++++++++++++++++++ .../tests/SmsClientLiveTestBase.cs | 1 - .../tests/SmsClientTest.cs | 38 +++ 7 files changed, 533 insertions(+), 14 deletions(-) create mode 100644 sdk/communication/Azure.Communication.Sms/tests/OptOutsClientTest.cs create mode 100644 sdk/communication/Azure.Communication.Sms/tests/OptOutsRestClientTests.cs diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/SmsModelFactory.cs b/sdk/communication/Azure.Communication.Sms/src/Models/SmsModelFactory.cs index 6529eadf5fee6..2b9ec57323c6d 100644 --- a/sdk/communication/Azure.Communication.Sms/src/Models/SmsModelFactory.cs +++ b/sdk/communication/Azure.Communication.Sms/src/Models/SmsModelFactory.cs @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#nullable disable - namespace Azure.Communication.Sms.Models { - /// Model factory for models. - public static partial class SmsModelFactory + /// + /// Model factory that enables mocking for the Sms library. + /// + public static class SmsModelFactory { /// Initializes a new instance of SmsSendResult. /// The recipient's phone number in E.164 format. @@ -15,6 +15,6 @@ public static partial class SmsModelFactory /// Indicates if the message is processed successfully or not. /// Optional error message in case of 4xx/5xx/repeatable errors. public static SmsSendResult SmsSendResult(string to, string messageId, int httpStatusCode, bool successful, string errorMessage) - => new SmsSendResult(to, messageId, httpStatusCode, SmsSendResponseItemRepeatabilityResult.Accepted, successful, errorMessage); + => new(to, messageId, httpStatusCode, SmsSendResponseItemRepeatabilityResult.Accepted, successful, errorMessage); } } diff --git a/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs b/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs index 871e82be385ac..fefadc9600e0a 100644 --- a/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs +++ b/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs @@ -1,13 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using Azure.Communication.Sms.Models; -using Azure.Core.Pipeline; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Threading; using System; +using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Azure.Communication.Sms.Models; +using Azure.Core.Pipeline; namespace Azure.Communication.Sms { @@ -20,9 +20,14 @@ public class OptOutsClient internal OptOutsRestClient OptOutsRestClient; - internal OptOutsClient(OptOutsRestClient optOutsRestClient, ClientDiagnostics clientDiagnostics) + internal OptOutsClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, Uri endpoint, string apiVersion = "2024-12-10-preview") { - OptOutsRestClient = optOutsRestClient; + Argument.CheckNotNull(clientDiagnostics, nameof(clientDiagnostics)); + Argument.CheckNotNull(pipeline, nameof(pipeline)); + Argument.CheckNotNull(endpoint, nameof(endpoint)); + Argument.CheckNotNull(apiVersion, nameof(apiVersion)); + + OptOutsRestClient = new OptOutsRestClient(clientDiagnostics, pipeline, endpoint, apiVersion); _clientDiagnostics = clientDiagnostics; } diff --git a/sdk/communication/Azure.Communication.Sms/src/SmsClient.cs b/sdk/communication/Azure.Communication.Sms/src/SmsClient.cs index 7c9a2a9832881..25f76646d59f2 100644 --- a/sdk/communication/Azure.Communication.Sms/src/SmsClient.cs +++ b/sdk/communication/Azure.Communication.Sms/src/SmsClient.cs @@ -83,7 +83,7 @@ private SmsClient(string endpoint, HttpPipeline httpPipeline, SmsClientOptions o { _clientDiagnostics = new ClientDiagnostics(options); RestClient = new SmsRestClient(_clientDiagnostics, httpPipeline, new Uri(endpoint), options.ApiVersion); - OptOuts = new OptOutsClient(new OptOutsRestClient(_clientDiagnostics, httpPipeline, new Uri(endpoint), options.ApiVersion), _clientDiagnostics); + OptOuts = new OptOutsClient(_clientDiagnostics, httpPipeline, new Uri(endpoint), options.ApiVersion); } #endregion diff --git a/sdk/communication/Azure.Communication.Sms/tests/OptOutsClientTest.cs b/sdk/communication/Azure.Communication.Sms/tests/OptOutsClientTest.cs new file mode 100644 index 0000000000000..a3fdf06404ac1 --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/tests/OptOutsClientTest.cs @@ -0,0 +1,198 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; +using Azure.Communication.Sms.Models; +using Azure.Core.Pipeline; +using Moq; +using NUnit.Framework; + +namespace Azure.Communication.Sms.Tests +{ + public class OptOutsClientTest + { + [Test] + public void OptOutsClient_ThrowsWithNullClientDiagnostics() + { + var httpPipeline = HttpPipelineBuilder.Build(new SmsClientOptions()); + var uri = new Uri("http://localhost"); + + Assert.Throws(() => new OptOutsClient(null, httpPipeline, uri)); + } + + [Test] + public void OptOutsClient_ThrowsWithNullPipeline() + { + var clientDiagnostics = new ClientDiagnostics(new SmsClientOptions()); + var uri = new Uri("http://localhost"); + + Assert.Throws(() => new OptOutsClient(clientDiagnostics, null, uri)); + } + + [Test] + public void OptOutsClient_ThrowsWithNullEndpoint() + { + var clientDiagnostics = new ClientDiagnostics(new SmsClientOptions()); + var httpPipeline = HttpPipelineBuilder.Build(new SmsClientOptions()); + + Assert.Throws(() => new OptOutsClient(clientDiagnostics, httpPipeline, null)); + } + + [TestCaseSource(nameof(TestData))] + public async Task CheckAsyncOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) + { + Mock mockClient = new Mock() { CallBase = true }; + Response? expectedResponse = default; + CancellationToken cancellationToken = new CancellationTokenSource().Token; + var callExpression = BuildExpression(x => x.CheckAsync(It.IsAny(), It.IsAny>(), It.IsAny())); + + mockClient + .Setup(callExpression) + .ReturnsAsync((string from, IEnumerable to, CancellationToken token) => + { + Assert.AreEqual(expectedFrom, from); + Assert.AreEqual(expectedTo, to); + Assert.AreEqual(cancellationToken, token); + return expectedResponse = new Mock>().Object; + }); + + Response actualResponse = await mockClient.Object.CheckAsync(expectedFrom, expectedTo, cancellationToken); + + mockClient.Verify(callExpression, Times.Once()); + Assert.AreEqual(expectedResponse, actualResponse); + } + + [TestCaseSource(nameof(TestData))] + public void CheckOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) + { + Mock mockClient = new Mock() { CallBase = true }; + Response? expectedResponse = default; + CancellationToken cancellationToken = new CancellationTokenSource().Token; + var callExpression = BuildExpression(x => x.Check(It.IsAny(), It.IsAny>(), It.IsAny())); + + mockClient + .Setup(callExpression) + .Returns((string from, IEnumerable to, CancellationToken token) => + { + Assert.AreEqual(expectedFrom, from); + Assert.AreEqual(expectedTo, to); + Assert.AreEqual(cancellationToken, token); + return expectedResponse = new Mock>().Object; + }); + + Response actualResponse = mockClient.Object.Check(expectedFrom, expectedTo, cancellationToken); + + mockClient.Verify(callExpression, Times.Once()); + Assert.AreEqual(expectedResponse, actualResponse); + } + + [TestCaseSource(nameof(TestData))] + public async Task AddAsyncOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) + { + Mock mockClient = new Mock() { CallBase = true }; + Response? expectedResponse = default; + CancellationToken cancellationToken = new CancellationTokenSource().Token; + var callExpression = BuildExpression(x => x.AddAsync(It.IsAny(), It.IsAny>(), It.IsAny())); + + mockClient + .Setup(callExpression) + .ReturnsAsync((string from, IEnumerable to, CancellationToken token) => + { + Assert.AreEqual(expectedFrom, from); + Assert.AreEqual(expectedTo, to); + Assert.AreEqual(cancellationToken, token); + return expectedResponse = new Mock>().Object; + }); + + Response actualResponse = await mockClient.Object.AddAsync(expectedFrom, expectedTo, cancellationToken); + + mockClient.Verify(callExpression, Times.Once()); + Assert.AreEqual(expectedResponse, actualResponse); + } + + [TestCaseSource(nameof(TestData))] + public void AddOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) + { + Mock mockClient = new Mock() { CallBase = true }; + Response? expectedResponse = default; + CancellationToken cancellationToken = new CancellationTokenSource().Token; + var callExpression = BuildExpression(x => x.Add(It.IsAny(), It.IsAny>(), It.IsAny())); + + mockClient + .Setup(callExpression) + .Returns((string from, IEnumerable to, CancellationToken token) => + { + Assert.AreEqual(expectedFrom, from); + Assert.AreEqual(expectedTo, to); + Assert.AreEqual(cancellationToken, token); + return expectedResponse = new Mock>().Object; + }); + + Response actualResponse = mockClient.Object.Add(expectedFrom, expectedTo, cancellationToken); + + mockClient.Verify(callExpression, Times.Once()); + Assert.AreEqual(expectedResponse, actualResponse); + } + + [TestCaseSource(nameof(TestData))] + public async Task RemoveAsyncOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) + { + Mock mockClient = new Mock() { CallBase = true }; + Response? expectedResponse = default; + CancellationToken cancellationToken = new CancellationTokenSource().Token; + var callExpression = BuildExpression(x => x.RemoveAsync(It.IsAny(), It.IsAny>(), It.IsAny())); + + mockClient + .Setup(callExpression) + .ReturnsAsync((string from, IEnumerable to, CancellationToken token) => + { + Assert.AreEqual(expectedFrom, from); + Assert.AreEqual(expectedTo, to); + Assert.AreEqual(cancellationToken, token); + return expectedResponse = new Mock>().Object; + }); + + Response actualResponse = await mockClient.Object.RemoveAsync(expectedFrom, expectedTo, cancellationToken); + + mockClient.Verify(callExpression, Times.Once()); + Assert.AreEqual(expectedResponse, actualResponse); + } + + [TestCaseSource(nameof(TestData))] + public void RemoveOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) + { + Mock mockClient = new Mock() { CallBase = true }; + Response? expectedResponse = default; + CancellationToken cancellationToken = new CancellationTokenSource().Token; + var callExpression = BuildExpression(x => x.Remove(It.IsAny(), It.IsAny>(), It.IsAny())); + + mockClient + .Setup(callExpression) + .Returns((string from, IEnumerable to, CancellationToken token) => + { + Assert.AreEqual(expectedFrom, from); + Assert.AreEqual(expectedTo, to); + Assert.AreEqual(cancellationToken, token); + return expectedResponse = new Mock>().Object; + }); + + Response actualResponse = mockClient.Object.Remove(expectedFrom, expectedTo, cancellationToken); + + mockClient.Verify(callExpression, Times.Once()); + Assert.AreEqual(expectedResponse, actualResponse); + } + + private static IEnumerable TestData() + { + yield return new TestCaseData("+14255550123", new List { "+14255550234" }); + } + + private static Expression> BuildExpression(Expression> expression) + => expression; + } +} diff --git a/sdk/communication/Azure.Communication.Sms/tests/OptOutsRestClientTests.cs b/sdk/communication/Azure.Communication.Sms/tests/OptOutsRestClientTests.cs new file mode 100644 index 0000000000000..d60fa853d64d3 --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/tests/OptOutsRestClientTests.cs @@ -0,0 +1,279 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Linq; +using System.Threading.Tasks; +using Azure.Communication.Sms.Models; +using Azure.Core.Pipeline; +using NUnit.Framework; + +namespace Azure.Communication.Sms.Tests +{ + public class OptOutsRestClientTests + { + [Test] + public void OptOutsRestClient_NullClientDiagnostics_ShouldThrow() + { + var httpPipeline = HttpPipelineBuilder.Build(new SmsClientOptions()); + var uri = new Uri("http://localhost"); + + Assert.Throws(() => new OptOutsRestClient(null, httpPipeline, uri)); + } + + [Test] + public void OptOutsRestClient_NullHttpPipeline_ShouldThrow() + { + var clientDiagnostics = new ClientDiagnostics(new SmsClientOptions()); + var endpoint = new Uri("http://localhost"); + + Assert.Throws(() => new OptOutsRestClient(clientDiagnostics, null, endpoint)); + } + + [Test] + public void OptOutsRestClient_NullEndpoint_ShouldThrow() + { + var clientDiagnostics = new ClientDiagnostics(new SmsClientOptions()); + var httpPipeline = HttpPipelineBuilder.Build(new SmsClientOptions()); + + Assert.Throws(() => new OptOutsRestClient(clientDiagnostics, httpPipeline, null)); + } + + [Test] + public void OptOutsRestClient_NullVersion_ShouldThrow() + { + var clientOptions = new SmsClientOptions(); + var clientDiagnostics = new ClientDiagnostics(clientOptions); + var httpPipeline = HttpPipelineBuilder.Build(clientOptions); + var uri = new Uri("http://localhost"); + + Assert.Throws(() => new OptOutsRestClient(clientDiagnostics, httpPipeline, uri, null)); + } + + [Test] + public void OptOutsRestClient_CheckWithNullSender_ShouldThrow() + { + var client = CreateOptOutsRestClient(); + + var recipients = Enumerable.Empty(); + + try + { + client.Check(null, recipients); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("from", ex.ParamName); + return; + } + } + + [Test] + public void OptOutsRestClient_CheckWithNullRecipients_ShouldThrow() + { + var client = CreateOptOutsRestClient(); + + var from = "+123456789"; + + try + { + client.Check(from, null); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("recipients", ex.ParamName); + return; + } + } + + [Test] + public async Task OptOutsRestClient_CheckAsyncWithNullSender_ShouldThrow() + { + var client = CreateOptOutsRestClient(); + + var recipients = Enumerable.Empty(); + + try + { + await client.CheckAsync(null, recipients); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("from", ex.ParamName); + return; + } + } + + [Test] + public async Task OptOutsRestClient_CheckAsyncWithNullRecipients_ShouldThrow() + { + var client = CreateOptOutsRestClient(); + + var from = "+123456789"; + + try + { + await client.CheckAsync(from, null); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("recipients", ex.ParamName); + return; + } + } + + [Test] + public void OptOutsRestClient_AddWithNullSender_ShouldThrow() + { + var client = CreateOptOutsRestClient(); + + var recipients = Enumerable.Empty(); + + try + { + client.Add(null, recipients); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("from", ex.ParamName); + return; + } + } + + [Test] + public void OptOutsRestClient_AddWithNullRecipients_ShouldThrow() + { + var client = CreateOptOutsRestClient(); + + var from = "+123456789"; + + try + { + client.Add(from, null); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("recipients", ex.ParamName); + return; + } + } + + [Test] + public async Task OptOutsRestClient_AddAsyncWithNullSender_ShouldThrow() + { + var client = CreateOptOutsRestClient(); + + var recipients = Enumerable.Empty(); + + try + { + await client.AddAsync(null, recipients); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("from", ex.ParamName); + return; + } + } + + [Test] + public async Task OptOutsRestClient_AddAsyncWithNullRecipients_ShouldThrow() + { + var client = CreateOptOutsRestClient(); + + var from = "+123456789"; + + try + { + await client.AddAsync(from, null); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("recipients", ex.ParamName); + return; + } + } + + [Test] + public void OptOutsRestClient_RemoveWithNullSender_ShouldThrow() + { + var client = CreateOptOutsRestClient(); + + var recipients = Enumerable.Empty(); + + try + { + client.Remove(null, recipients); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("from", ex.ParamName); + return; + } + } + + [Test] + public void OptOutsRestClient_RemoveWithNullRecipients_ShouldThrow() + { + var client = CreateOptOutsRestClient(); + + var from = "+123456789"; + + try + { + client.Remove(from, null); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("recipients", ex.ParamName); + return; + } + } + + [Test] + public async Task OptOutsRestClient_RemoveAsyncWithNullSender_ShouldThrow() + { + var client = CreateOptOutsRestClient(); + + var recipients = Enumerable.Empty(); + + try + { + await client.RemoveAsync(null, recipients); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("from", ex.ParamName); + return; + } + } + + [Test] + public async Task OptOutsRestClient_RemoveAsyncWithNullRecipients_ShouldThrow() + { + var client = CreateOptOutsRestClient(); + + var from = "+123456789"; + + try + { + await client.RemoveAsync(from, null); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("recipients", ex.ParamName); + return; + } + } + + private OptOutsRestClient CreateOptOutsRestClient() + { + var clientOptions = new SmsClientOptions(); + var clientDiagnostics = new ClientDiagnostics(clientOptions); + var httpPipeline = HttpPipelineBuilder.Build(clientOptions); + var endpoint = new Uri("http://localhost"); + + return new OptOutsRestClient(clientDiagnostics, httpPipeline, endpoint); + } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTestBase.cs b/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTestBase.cs index f5627810d2770..946697b830f27 100644 --- a/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTestBase.cs +++ b/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTestBase.cs @@ -5,7 +5,6 @@ using Azure.Core; using Azure.Core.TestFramework; using Azure.Core.TestFramework.Models; -using Azure.Identity; using NUnit.Framework; namespace Azure.Communication.Sms.Tests diff --git a/sdk/communication/Azure.Communication.Sms/tests/SmsClientTest.cs b/sdk/communication/Azure.Communication.Sms/tests/SmsClientTest.cs index ac1a581c25ab8..aec5eda500aa1 100644 --- a/sdk/communication/Azure.Communication.Sms/tests/SmsClientTest.cs +++ b/sdk/communication/Azure.Communication.Sms/tests/SmsClientTest.cs @@ -16,6 +16,8 @@ namespace Azure.Communication.Sms.Tests { public class SmsClientTest { + public string TestConnectionString = "Endpoint=https://your-acs-endpoint.com/;AccessKey=your-access-key;AccessKeySecret=your-access-key-secret"; + [Test] public void SmsClient_ThrowsWithNullKeyCredential() { @@ -66,6 +68,42 @@ public void SmsClientOptions_ThrowsWithInvalidVersion() Assert.Throws(() => new SmsClientOptions(invalidServiceVersion)); } + [Test] + public void SmsClient_InitializesOptOutsClient_SingleArgConstructor() + { + var smsClient = new SmsClient(TestConnectionString); + + Assert.NotNull(smsClient.OptOuts); + } + + [Test] + public void SmsClient_InitializesOptOutsClient_TwoArgConstructor() + { + var smsClient = new SmsClient(TestConnectionString, new SmsClientOptions(SmsClientOptions.ServiceVersion.V2021_03_07)); + + Assert.NotNull(smsClient.OptOuts); + } + + [Test] + public void SmsClient_InitializesOptOutsClient_ThreeArgConstructor() + { + AzureKeyCredential mockCredential = new AzureKeyCredential("mockKey"); + Uri endpoint = new Uri("http://localhost"); + var smsClient = new SmsClient(endpoint, mockCredential, new SmsClientOptions(SmsClientOptions.ServiceVersion.V2021_03_07)); + + Assert.NotNull(smsClient.OptOuts); + } + + [Test] + public void SmsClient_InitializesOptOutsClient_ThreeArgConstructor_WithTokenCredential() + { + TokenCredential mockCredential = new MockCredential(); + Uri endpoint = new Uri("http://localhost"); + var smsClient = new SmsClient(endpoint, mockCredential, new SmsClientOptions(SmsClientOptions.ServiceVersion.V2021_03_07)); + + Assert.NotNull(smsClient.OptOuts); + } + [TestCaseSource(nameof(TestDataForSingleSms))] public async Task SendSmsAsyncOverload_PassesToGeneratedOne(string expectedFrom, string expectedTo, string expectedMessage, SmsSendOptions expectedOptions) { From d3f9ea8162d856f16577900ab197dabff21d1caf Mon Sep 17 00:00:00 2001 From: FarhadJabiyev Date: Mon, 25 Nov 2024 17:43:04 +0200 Subject: [PATCH 3/9] Add new live tests --- .../src/OptOutsClient.cs | 36 ++--- .../tests/OptOutsClientTest.cs | 37 +++-- .../tests/SmsClientLiveTests.cs | 145 ++++++++++++++++-- 3 files changed, 169 insertions(+), 49 deletions(-) diff --git a/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs b/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs index fefadc9600e0a..c62bb86500229 100644 --- a/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs +++ b/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs @@ -47,9 +47,9 @@ protected OptOutsClient() /// The server returned an error. See for details returned from the server. /// is null. /// is null. - public virtual async Task> CheckAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) + public virtual async Task>> CheckAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) { - using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(SmsClient)}.{nameof(OptOutsClient)}.{nameof(CheckAsync)}"); + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(OptOutsClient)}.{nameof(Check)}"); scope.Start(); try { @@ -58,7 +58,7 @@ public virtual async Task> CheckAsync(string from, IEnu IEnumerable recipients = to.Select(x => new OptOutRecipient(Argument.CheckNotNullOrEmpty(x, nameof(to)))); Response response = await OptOutsRestClient.CheckAsync(from, recipients, cancellationToken).ConfigureAwait(false); - return Response.FromValue(response.Value, response.GetRawResponse()); + return Response.FromValue(response.Value.Value, response.GetRawResponse()); } catch (Exception ex) { @@ -76,9 +76,9 @@ public virtual async Task> CheckAsync(string from, IEnu /// The server returned an error. See for details returned from the server. /// is null. /// is null. - public virtual Response Check(string from, IEnumerable to, CancellationToken cancellationToken = default) + public virtual Response> Check(string from, IEnumerable to, CancellationToken cancellationToken = default) { - using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(SmsClient)}.{nameof(OptOutsClient)}.{nameof(Check)}"); + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(OptOutsClient)}.{nameof(Check)}"); scope.Start(); try { @@ -88,7 +88,7 @@ public virtual Response Check(string from, IEnumerable t IEnumerable recipients = to.Select(x => new OptOutRecipient(Argument.CheckNotNullOrEmpty(x, nameof(to)))); Response response = OptOutsRestClient.Check(from, recipients, cancellationToken); - return Response.FromValue(response.Value, response.GetRawResponse()); + return Response.FromValue(response.Value.Value, response.GetRawResponse()); } catch (Exception ex) { @@ -106,9 +106,9 @@ public virtual Response Check(string from, IEnumerable t /// The server returned an error. See for details returned from the server. /// is null. /// is null. - public virtual async Task> AddAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) + public virtual async Task>> AddAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) { - using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(SmsClient)}.{nameof(OptOutsClient)}.{nameof(AddAsync)}"); + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(OptOutsClient)}.{nameof(Add)}"); scope.Start(); try { @@ -119,7 +119,7 @@ public virtual async Task> AddAsync(string from, Response response = await OptOutsRestClient.AddAsync(from, recipients, cancellationToken).ConfigureAwait(false); OptOutChangeResponse result = new OptOutChangeResponse(response.Value.Value.Select(r => new OptOutChangeResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); - return Response.FromValue(result, response.GetRawResponse()); + return Response.FromValue(result.Value, response.GetRawResponse()); } catch (Exception ex) { @@ -137,9 +137,9 @@ public virtual async Task> AddAsync(string from, /// The server returned an error. See for details returned from the server. /// is null. /// is null. - public virtual Response Add(string from, IEnumerable to, CancellationToken cancellationToken = default) + public virtual Response> Add(string from, IEnumerable to, CancellationToken cancellationToken = default) { - using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(SmsClient)}.{nameof(OptOutsClient)}.{nameof(Add)}"); + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(OptOutsClient)}.{nameof(Add)}"); scope.Start(); try { @@ -150,7 +150,7 @@ public virtual Response Add(string from, IEnumerable response = OptOutsRestClient.Add(from, recipients, cancellationToken); OptOutChangeResponse result = new OptOutChangeResponse(response.Value.Value.Select(r => new OptOutChangeResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); - return Response.FromValue(result, response.GetRawResponse()); + return Response.FromValue(result.Value, response.GetRawResponse()); } catch (Exception ex) { @@ -168,9 +168,9 @@ public virtual Response Add(string from, IEnumerableThe server returned an error. See for details returned from the server. /// is null. /// is null. - public virtual async Task> RemoveAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) + public virtual async Task>> RemoveAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) { - using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(SmsClient)}.{nameof(OptOutsClient)}.{nameof(RemoveAsync)}"); + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(OptOutsClient)}.{nameof(Remove)}"); scope.Start(); try { @@ -181,7 +181,7 @@ public virtual async Task> RemoveAsync(string fro Response response = await OptOutsRestClient.RemoveAsync(from, recipients, cancellationToken).ConfigureAwait(false); OptOutChangeResponse result = new OptOutChangeResponse(response.Value.Value.Select(r => new OptOutChangeResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); - return Response.FromValue(result, response.GetRawResponse()); + return Response.FromValue(result.Value, response.GetRawResponse()); } catch (Exception ex) { @@ -199,9 +199,9 @@ public virtual async Task> RemoveAsync(string fro /// The server returned an error. See for details returned from the server. /// is null. /// is null. - public virtual Response Remove(string from, IEnumerable to, CancellationToken cancellationToken = default) + public virtual Response> Remove(string from, IEnumerable to, CancellationToken cancellationToken = default) { - using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(SmsClient)}.{nameof(OptOutsClient)}.{nameof(Remove)}"); + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(OptOutsClient)}.{nameof(Remove)}"); scope.Start(); try { @@ -212,7 +212,7 @@ public virtual Response Remove(string from, IEnumerable response = OptOutsRestClient.Remove(from, recipients, cancellationToken); OptOutChangeResponse result = new OptOutChangeResponse(response.Value.Value.Select(r => new OptOutChangeResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); - return Response.FromValue(result, response.GetRawResponse()); + return Response.FromValue(result.Value, response.GetRawResponse()); } catch (Exception ex) { diff --git a/sdk/communication/Azure.Communication.Sms/tests/OptOutsClientTest.cs b/sdk/communication/Azure.Communication.Sms/tests/OptOutsClientTest.cs index a3fdf06404ac1..509d00d6250d0 100644 --- a/sdk/communication/Azure.Communication.Sms/tests/OptOutsClientTest.cs +++ b/sdk/communication/Azure.Communication.Sms/tests/OptOutsClientTest.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; @@ -47,7 +46,7 @@ public void OptOutsClient_ThrowsWithNullEndpoint() public async Task CheckAsyncOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) { Mock mockClient = new Mock() { CallBase = true }; - Response? expectedResponse = default; + Response>? expectedResponse = default; CancellationToken cancellationToken = new CancellationTokenSource().Token; var callExpression = BuildExpression(x => x.CheckAsync(It.IsAny(), It.IsAny>(), It.IsAny())); @@ -58,10 +57,10 @@ public async Task CheckAsyncOverload_PassesToGeneratedOne(string expectedFrom, I Assert.AreEqual(expectedFrom, from); Assert.AreEqual(expectedTo, to); Assert.AreEqual(cancellationToken, token); - return expectedResponse = new Mock>().Object; + return expectedResponse = new Mock>>().Object; }); - Response actualResponse = await mockClient.Object.CheckAsync(expectedFrom, expectedTo, cancellationToken); + Response> actualResponse = await mockClient.Object.CheckAsync(expectedFrom, expectedTo, cancellationToken); mockClient.Verify(callExpression, Times.Once()); Assert.AreEqual(expectedResponse, actualResponse); @@ -71,7 +70,7 @@ public async Task CheckAsyncOverload_PassesToGeneratedOne(string expectedFrom, I public void CheckOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) { Mock mockClient = new Mock() { CallBase = true }; - Response? expectedResponse = default; + Response>? expectedResponse = default; CancellationToken cancellationToken = new CancellationTokenSource().Token; var callExpression = BuildExpression(x => x.Check(It.IsAny(), It.IsAny>(), It.IsAny())); @@ -82,10 +81,10 @@ public void CheckOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable< Assert.AreEqual(expectedFrom, from); Assert.AreEqual(expectedTo, to); Assert.AreEqual(cancellationToken, token); - return expectedResponse = new Mock>().Object; + return expectedResponse = new Mock>>().Object; }); - Response actualResponse = mockClient.Object.Check(expectedFrom, expectedTo, cancellationToken); + Response> actualResponse = mockClient.Object.Check(expectedFrom, expectedTo, cancellationToken); mockClient.Verify(callExpression, Times.Once()); Assert.AreEqual(expectedResponse, actualResponse); @@ -95,7 +94,7 @@ public void CheckOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable< public async Task AddAsyncOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) { Mock mockClient = new Mock() { CallBase = true }; - Response? expectedResponse = default; + Response>? expectedResponse = default; CancellationToken cancellationToken = new CancellationTokenSource().Token; var callExpression = BuildExpression(x => x.AddAsync(It.IsAny(), It.IsAny>(), It.IsAny())); @@ -106,10 +105,10 @@ public async Task AddAsyncOverload_PassesToGeneratedOne(string expectedFrom, IEn Assert.AreEqual(expectedFrom, from); Assert.AreEqual(expectedTo, to); Assert.AreEqual(cancellationToken, token); - return expectedResponse = new Mock>().Object; + return expectedResponse = new Mock>>().Object; }); - Response actualResponse = await mockClient.Object.AddAsync(expectedFrom, expectedTo, cancellationToken); + Response> actualResponse = await mockClient.Object.AddAsync(expectedFrom, expectedTo, cancellationToken); mockClient.Verify(callExpression, Times.Once()); Assert.AreEqual(expectedResponse, actualResponse); @@ -119,7 +118,7 @@ public async Task AddAsyncOverload_PassesToGeneratedOne(string expectedFrom, IEn public void AddOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) { Mock mockClient = new Mock() { CallBase = true }; - Response? expectedResponse = default; + Response>? expectedResponse = default; CancellationToken cancellationToken = new CancellationTokenSource().Token; var callExpression = BuildExpression(x => x.Add(It.IsAny(), It.IsAny>(), It.IsAny())); @@ -130,10 +129,10 @@ public void AddOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable>().Object; + return expectedResponse = new Mock>>().Object; }); - Response actualResponse = mockClient.Object.Add(expectedFrom, expectedTo, cancellationToken); + Response> actualResponse = mockClient.Object.Add(expectedFrom, expectedTo, cancellationToken); mockClient.Verify(callExpression, Times.Once()); Assert.AreEqual(expectedResponse, actualResponse); @@ -143,7 +142,7 @@ public void AddOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) { Mock mockClient = new Mock() { CallBase = true }; - Response? expectedResponse = default; + Response>? expectedResponse = default; CancellationToken cancellationToken = new CancellationTokenSource().Token; var callExpression = BuildExpression(x => x.RemoveAsync(It.IsAny(), It.IsAny>(), It.IsAny())); @@ -154,10 +153,10 @@ public async Task RemoveAsyncOverload_PassesToGeneratedOne(string expectedFrom, Assert.AreEqual(expectedFrom, from); Assert.AreEqual(expectedTo, to); Assert.AreEqual(cancellationToken, token); - return expectedResponse = new Mock>().Object; + return expectedResponse = new Mock>>().Object; }); - Response actualResponse = await mockClient.Object.RemoveAsync(expectedFrom, expectedTo, cancellationToken); + Response> actualResponse = await mockClient.Object.RemoveAsync(expectedFrom, expectedTo, cancellationToken); mockClient.Verify(callExpression, Times.Once()); Assert.AreEqual(expectedResponse, actualResponse); @@ -167,7 +166,7 @@ public async Task RemoveAsyncOverload_PassesToGeneratedOne(string expectedFrom, public void RemoveOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) { Mock mockClient = new Mock() { CallBase = true }; - Response? expectedResponse = default; + Response>? expectedResponse = default; CancellationToken cancellationToken = new CancellationTokenSource().Token; var callExpression = BuildExpression(x => x.Remove(It.IsAny(), It.IsAny>(), It.IsAny())); @@ -178,10 +177,10 @@ public void RemoveOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable Assert.AreEqual(expectedFrom, from); Assert.AreEqual(expectedTo, to); Assert.AreEqual(cancellationToken, token); - return expectedResponse = new Mock>().Object; + return expectedResponse = new Mock>>().Object; }); - Response actualResponse = mockClient.Object.Remove(expectedFrom, expectedTo, cancellationToken); + Response> actualResponse = mockClient.Object.Remove(expectedFrom, expectedTo, cancellationToken); mockClient.Verify(callExpression, Times.Once()); Assert.AreEqual(expectedResponse, actualResponse); diff --git a/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTests.cs b/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTests.cs index 6ca4be841d952..77b83a6296ec2 100644 --- a/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTests.cs +++ b/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTests.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using NUnit.Framework; +using Azure.Communication.Sms.Models; namespace Azure.Communication.Sms.Tests { @@ -31,8 +32,8 @@ public async Task SendingSmsMessage() message: "Hi"); SmsSendResult result = response.Value; Console.WriteLine($"Sms id: {result.MessageId}"); - AssertHappyPath(result); - AssertRawResponseHappyPath(response.GetRawResponse().ContentStream ?? new MemoryStream()); + AssertSmsSendingHappyPath(result); + AssertSmsSendingRawResponseHappyPath(response.GetRawResponse().ContentStream ?? new MemoryStream()); } catch (RequestFailedException ex) { @@ -57,8 +58,8 @@ public async Task SendingSmsMessageUsingTokenCredential() message: "Hi"); SmsSendResult result = response.Value; Console.WriteLine($"Sms id: {result.MessageId}"); - AssertHappyPath(result); - AssertRawResponseHappyPath(response.GetRawResponse().ContentStream ?? new MemoryStream()); + AssertSmsSendingHappyPath(result); + AssertSmsSendingRawResponseHappyPath(response.GetRawResponse().ContentStream ?? new MemoryStream()); } catch (RequestFailedException ex) { @@ -110,11 +111,11 @@ public async Task SendingSmsMessageToGroupWithOptions() Tag = "marketing", // custom tags DeliveryReportTimeoutInSeconds = 90 // OPTIONAL }); - AssertRawResponseHappyPath(response.GetRawResponse().ContentStream ?? new MemoryStream()); + AssertSmsSendingRawResponseHappyPath(response.GetRawResponse().ContentStream ?? new MemoryStream()); foreach (SmsSendResult result in response.Value) { Console.WriteLine($"Sms id: {result.MessageId}"); - AssertHappyPath(result); + AssertSmsSendingHappyPath(result); } } catch (RequestFailedException ex) @@ -143,15 +144,15 @@ public async Task SendingTwoSmsMessages() to: TestEnvironment.ToPhoneNumber, message: "Hi"); - AssertRawResponseHappyPath(firstMessageResponse.GetRawResponse().ContentStream ?? new MemoryStream()); - AssertRawResponseHappyPath(secondMessageResponse.GetRawResponse().ContentStream ?? new MemoryStream()); + AssertSmsSendingRawResponseHappyPath(firstMessageResponse.GetRawResponse().ContentStream ?? new MemoryStream()); + AssertSmsSendingRawResponseHappyPath(secondMessageResponse.GetRawResponse().ContentStream ?? new MemoryStream()); SmsSendResult firstMessageResult = firstMessageResponse.Value; SmsSendResult secondMessageResult = secondMessageResponse.Value; Assert.AreNotEqual(firstMessageResult.MessageId, secondMessageResult.MessageId); - AssertHappyPath(firstMessageResult); - AssertHappyPath(secondMessageResult); + AssertSmsSendingHappyPath(firstMessageResult); + AssertSmsSendingHappyPath(secondMessageResult); } catch (RequestFailedException ex) { @@ -203,14 +204,134 @@ public async Task SendingSmsToNullNumberShouldThrow() Assert.Fail("SendAsync should have thrown an exception."); } - private void AssertHappyPath(SmsSendResult sendResult) + [Test] + public async Task CheckOptOutFromNullNumberShouldThrow() + { + SmsClient client = CreateSmsClient(); + try + { + IEnumerable? to = new string[] { TestEnvironment.ToPhoneNumber }; + Response> result = await client.OptOuts.CheckAsync( + from: null, + to: to); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("from", ex.ParamName); + return; + } + Assert.Fail("CheckAsync should have thrown an exception."); + } + + [Test] + public async Task CheckOptOutToNullNumberShouldThrow() + { + SmsClient client = CreateSmsClient(); + try + { + IEnumerable? to = null; + Response> result = await client.OptOuts.CheckAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("to", ex.ParamName); + return; + } + Assert.Fail("CheckAsync should have thrown an exception."); + } + + [Test] + public async Task CheckOptOutToCollectionContainingNullShouldThrow() + { + SmsClient client = CreateSmsClient(); + try + { +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. + IEnumerable? to = new string[] + { + TestEnvironment.ToPhoneNumber, + null + }; +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. + + Response> result = await client.OptOuts.CheckAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("to", ex.ParamName); + return; + } + Assert.Fail("CheckAsync should have thrown an exception."); + } + + [Test] + public async Task AddOptOutEndpointShouldMarkRecipientAsOptedOut() + { + SmsClient client = CreateSmsClient(); + try + { + IEnumerable? to = new[] { TestEnvironment.ToPhoneNumber }; + + Response> addResult = await client.OptOuts.AddAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + + Response> checkResult = await client.OptOuts.CheckAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + + Assert.IsTrue(checkResult.Value[0].IsOptedOut); + } + catch (Exception ex) + { + Assert.Fail("Exception should not have been thrown."); + Console.WriteLine(ex); + return; + } + } + + [Test] + public async Task RemoveOptOutEndpointShouldMarkRecipientAsOptedIn() + { + SmsClient client = CreateSmsClient(); + try + { + IEnumerable? to = new[] { TestEnvironment.ToPhoneNumber }; + + Response> addResult = await client.OptOuts.AddAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + + Response> removeResult = await client.OptOuts.RemoveAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + + Response> checkResult = await client.OptOuts.CheckAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + + Assert.IsFalse(checkResult.Value[0].IsOptedOut); + } + catch (Exception ex) + { + Assert.Fail("Exception should not have been thrown."); + Console.WriteLine(ex); + return; + } + } + + private void AssertSmsSendingHappyPath(SmsSendResult sendResult) { Assert.True(sendResult.Successful); Assert.AreEqual(202, sendResult.HttpStatusCode); Assert.IsFalse(string.IsNullOrWhiteSpace(sendResult.MessageId)); } - private void AssertRawResponseHappyPath(Stream contentStream) + private void AssertSmsSendingRawResponseHappyPath(Stream contentStream) { if (contentStream.Length > 0) { From f4c6677dad2bcf8a5843ded914ee74263cd27804 Mon Sep 17 00:00:00 2001 From: FarhadJabiyev Date: Tue, 26 Nov 2024 13:44:14 +0200 Subject: [PATCH 4/9] Update spec acpi url --- sdk/communication/Azure.Communication.Sms/src/autorest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/communication/Azure.Communication.Sms/src/autorest.md b/sdk/communication/Azure.Communication.Sms/src/autorest.md index ec53a5658606c..46a277e35bfa0 100644 --- a/sdk/communication/Azure.Communication.Sms/src/autorest.md +++ b/sdk/communication/Azure.Communication.Sms/src/autorest.md @@ -9,7 +9,7 @@ Run `dotnet msbuild /t:GenerateCode` to generate code. tag: package-sms-2024-12-10-preview model-namespace: true require: - - C:\azure-rest-api-specs\specification\communication\data-plane\Sms\readme.md + - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/b538b6ec5e8ea500a60a5708e2cb046705a62114/specification/communication/data-plane/Sms/readme.md payload-flattening-threshold: 10 generation1-convenience-client: true ``` From b6fa58926388df6c3b2656397f9f5281009a069d Mon Sep 17 00:00:00 2001 From: FarhadJabiyev Date: Tue, 26 Nov 2024 16:19:33 +0200 Subject: [PATCH 5/9] Update api --- .../api/Azure.Communication.Sms.net8.0.cs | 50 ++++++++++++++++++- .../Azure.Communication.Sms.netstandard2.0.cs | 12 ++--- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.net8.0.cs b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.net8.0.cs index bf2d7f3d8a534..4a86cb4478f63 100644 --- a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.net8.0.cs +++ b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.net8.0.cs @@ -1,5 +1,15 @@ namespace Azure.Communication.Sms { + public partial class OptOutsClient + { + protected OptOutsClient() { } + public virtual Azure.Response> Add(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task>> AddAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response> Check(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task>> CheckAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response> Remove(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task>> RemoveAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + } public partial class SmsClient { protected SmsClient() { } @@ -7,6 +17,7 @@ public SmsClient(string connectionString) { } public SmsClient(string connectionString, Azure.Communication.Sms.SmsClientOptions options) { } public SmsClient(System.Uri endpoint, Azure.AzureKeyCredential keyCredential, Azure.Communication.Sms.SmsClientOptions options = null) { } public SmsClient(System.Uri endpoint, Azure.Core.TokenCredential tokenCredential, Azure.Communication.Sms.SmsClientOptions options = null) { } + public virtual Azure.Communication.Sms.OptOutsClient OptOuts { get { throw null; } } public virtual Azure.Response> Send(string from, System.Collections.Generic.IEnumerable to, string message, Azure.Communication.Sms.SmsSendOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response Send(string from, string to, string message, Azure.Communication.Sms.SmsSendOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task>> SendAsync(string from, System.Collections.Generic.IEnumerable to, string message, Azure.Communication.Sms.SmsSendOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -14,11 +25,11 @@ public SmsClient(System.Uri endpoint, Azure.Core.TokenCredential tokenCredential } public partial class SmsClientOptions : Azure.Core.ClientOptions { - public SmsClientOptions(Azure.Communication.Sms.SmsClientOptions.ServiceVersion version = Azure.Communication.Sms.SmsClientOptions.ServiceVersion.V2024_02_05_Preview) { } + public SmsClientOptions(Azure.Communication.Sms.SmsClientOptions.ServiceVersion version = Azure.Communication.Sms.SmsClientOptions.ServiceVersion.V2024_12_10_Preview) { } public enum ServiceVersion { V2021_03_07 = 1, - V2024_02_05_Preview = 2, + V2024_12_10_Preview = 2, } } public partial class SmsSendOptions @@ -40,6 +51,41 @@ internal SmsSendResult() { } } namespace Azure.Communication.Sms.Models { + public static partial class CommunicationSmsModelFactory + { + public static Azure.Communication.Sms.Models.OptOutResponse OptOutResponse(System.Collections.Generic.IEnumerable value = null) { throw null; } + public static Azure.Communication.Sms.Models.OptOutResponseItem OptOutResponseItem(string to = null, int httpStatusCode = 0, bool? isOptedOut = default(bool?), string errorMessage = null) { throw null; } + } + public partial class OptOutChangeResponse + { + internal OptOutChangeResponse() { } + public System.Collections.Generic.IReadOnlyList Value { get { throw null; } } + } + public partial class OptOutChangeResponseItem + { + internal OptOutChangeResponseItem() { } + public string ErrorMessage { get { throw null; } } + public int HttpStatusCode { get { throw null; } } + public string To { get { throw null; } } + } + public partial class OptOutRecipient + { + public OptOutRecipient(string to) { } + public string To { get { throw null; } } + } + public partial class OptOutResponse + { + internal OptOutResponse() { } + public System.Collections.Generic.IReadOnlyList Value { get { throw null; } } + } + public partial class OptOutResponseItem + { + internal OptOutResponseItem() { } + public string ErrorMessage { get { throw null; } } + public int HttpStatusCode { get { throw null; } } + public bool? IsOptedOut { get { throw null; } } + public string To { get { throw null; } } + } public static partial class SmsModelFactory { public static Azure.Communication.Sms.SmsSendResult SmsSendResult(string to, string messageId, int httpStatusCode, bool successful, string errorMessage) { throw null; } diff --git a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs index a92d13996fc00..4a86cb4478f63 100644 --- a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs +++ b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs @@ -3,12 +3,12 @@ namespace Azure.Communication.Sms public partial class OptOutsClient { protected OptOutsClient() { } - public virtual Azure.Response Add(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual System.Threading.Tasks.Task> AddAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual Azure.Response Check(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual System.Threading.Tasks.Task> CheckAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual Azure.Response Remove(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual System.Threading.Tasks.Task> RemoveAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response> Add(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task>> AddAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response> Check(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task>> CheckAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response> Remove(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task>> RemoveAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } public partial class SmsClient { From 9073c5bfadd0dffaf50aa0a9f3693968052fdce2 Mon Sep 17 00:00:00 2001 From: FarhadJabiyev Date: Wed, 27 Nov 2024 16:32:17 +0200 Subject: [PATCH 6/9] Push assets --- sdk/communication/Azure.Communication.Sms/assets.json | 2 +- .../Azure.Communication.Sms/src/SmsClientOptions.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/communication/Azure.Communication.Sms/assets.json b/sdk/communication/Azure.Communication.Sms/assets.json index 214ae3972dad7..7da6c4c726506 100644 --- a/sdk/communication/Azure.Communication.Sms/assets.json +++ b/sdk/communication/Azure.Communication.Sms/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "net", "TagPrefix": "net/communication/Azure.Communication.Sms", - "Tag": "net/communication/Azure.Communication.Sms_3b274f81e7" + "Tag": "net/communication/Azure.Communication.Sms_d47e835d96" } diff --git a/sdk/communication/Azure.Communication.Sms/src/SmsClientOptions.cs b/sdk/communication/Azure.Communication.Sms/src/SmsClientOptions.cs index d76b0536f99f2..3f1a44ff26a37 100644 --- a/sdk/communication/Azure.Communication.Sms/src/SmsClientOptions.cs +++ b/sdk/communication/Azure.Communication.Sms/src/SmsClientOptions.cs @@ -42,7 +42,7 @@ public enum ServiceVersion /// V2021_03_07 = 1, /// - /// The "2024-02-05-preview" of the Sms service. + /// The "2024-12-10-preview" of the Sms service. /// V2024_12_10_Preview = 2 #pragma warning restore CA1707 // Identifiers should not contain underscores From a9c8bb2968aad57439142e0089285aedb9a2f0a6 Mon Sep 17 00:00:00 2001 From: FarhadJabiyev Date: Thu, 28 Nov 2024 11:45:25 +0200 Subject: [PATCH 7/9] Push tests --- .../api/Azure.Communication.Sms.net8.0.cs | 6 +- .../Azure.Communication.Sms.netstandard2.0.cs | 6 +- .../Azure.Communication.Sms/assets.json | 2 +- .../src/Models/OptOutChangeResponse.cs | 2 +- .../src/Models/OptOutChangeResponseItem.cs | 2 +- .../tests/SmsClientLiveTests.cs | 57 +++++++++++++++++++ 6 files changed, 68 insertions(+), 7 deletions(-) diff --git a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.net8.0.cs b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.net8.0.cs index 4a86cb4478f63..ce2f3be00a9c7 100644 --- a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.net8.0.cs +++ b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.net8.0.cs @@ -61,9 +61,11 @@ public partial class OptOutChangeResponse internal OptOutChangeResponse() { } public System.Collections.Generic.IReadOnlyList Value { get { throw null; } } } - public partial class OptOutChangeResponseItem + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public partial struct OptOutChangeResponseItem { - internal OptOutChangeResponseItem() { } + private object _dummy; + private int _dummyPrimitive; public string ErrorMessage { get { throw null; } } public int HttpStatusCode { get { throw null; } } public string To { get { throw null; } } diff --git a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs index 4a86cb4478f63..ce2f3be00a9c7 100644 --- a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs +++ b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs @@ -61,9 +61,11 @@ public partial class OptOutChangeResponse internal OptOutChangeResponse() { } public System.Collections.Generic.IReadOnlyList Value { get { throw null; } } } - public partial class OptOutChangeResponseItem + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public partial struct OptOutChangeResponseItem { - internal OptOutChangeResponseItem() { } + private object _dummy; + private int _dummyPrimitive; public string ErrorMessage { get { throw null; } } public int HttpStatusCode { get { throw null; } } public string To { get { throw null; } } diff --git a/sdk/communication/Azure.Communication.Sms/assets.json b/sdk/communication/Azure.Communication.Sms/assets.json index 7da6c4c726506..15352d38fbd30 100644 --- a/sdk/communication/Azure.Communication.Sms/assets.json +++ b/sdk/communication/Azure.Communication.Sms/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "net", "TagPrefix": "net/communication/Azure.Communication.Sms", - "Tag": "net/communication/Azure.Communication.Sms_d47e835d96" + "Tag": "net/communication/Azure.Communication.Sms_363bacad7d" } diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponse.cs b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponse.cs index 38b02296c11c8..b555150e69ee4 100644 --- a/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponse.cs +++ b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponse.cs @@ -7,7 +7,7 @@ namespace Azure.Communication.Sms.Models { - /// Response for an opt out request. Validate the returned items in the response to see which recipients were successfully added or removed from the opt outs list. + /// Response for an add and remove opt out request. Validate the returned items in the response to see which recipients were successfully added or removed from the opt outs list. public partial class OptOutChangeResponse { /// Initializes a new instance of . diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponseItem.cs b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponseItem.cs index 48e380b15273a..9b4c911377268 100644 --- a/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponseItem.cs +++ b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponseItem.cs @@ -6,7 +6,7 @@ namespace Azure.Communication.Sms.Models { /// The OptOutChangeResponseItem. - public class OptOutChangeResponseItem + public struct OptOutChangeResponseItem { /// Initializes a new instance of . /// The recipient phone number (in E.164 format). diff --git a/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTests.cs b/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTests.cs index 77b83a6296ec2..85c7cd0727a8b 100644 --- a/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTests.cs +++ b/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTests.cs @@ -324,6 +324,63 @@ public async Task RemoveOptOutEndpointShouldMarkRecipientAsOptedIn() } } + [Test] + public async Task AddOptOutEndpointShouldMarkRecipientsAsOptedOut() + { + SmsClient client = CreateSmsClient(); + try + { + IEnumerable? to = new[] { TestEnvironment.ToPhoneNumber, TestEnvironment.ToPhoneNumber }; + + Response> addResult = await client.OptOuts.AddAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + + Response> checkResult = await client.OptOuts.CheckAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + + Assert.IsTrue(checkResult.Value[0].IsOptedOut); + Assert.IsTrue(checkResult.Value[1].IsOptedOut); + } + catch (Exception ex) + { + Assert.Fail("Exception should not have been thrown."); + Console.WriteLine(ex); + return; + } + } + + [Test] + public async Task RemoveOptOutEndpointShouldMarkRecipientsAsOptedIn() + { + SmsClient client = CreateSmsClient(); + try + { + IEnumerable? to = new[] { TestEnvironment.ToPhoneNumber, TestEnvironment.ToPhoneNumber }; + + Response> addResult = await client.OptOuts.AddAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + + Response> removeResult = await client.OptOuts.RemoveAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + + Response> checkResult = await client.OptOuts.CheckAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + + Assert.IsFalse(checkResult.Value[0].IsOptedOut); + } + catch (Exception ex) + { + Assert.Fail("Exception should not have been thrown."); + Console.WriteLine(ex); + return; + } + } + private void AssertSmsSendingHappyPath(SmsSendResult sendResult) { Assert.True(sendResult.Successful); From e3ed05d14f4b85972bc8aa819875552b07808579 Mon Sep 17 00:00:00 2001 From: FarhadJabiyev Date: Thu, 28 Nov 2024 15:56:48 +0200 Subject: [PATCH 8/9] Different models for opt add and remove endpoints, few more live tests --- .../Azure.Communication.Sms/CHANGELOG.md | 12 +- .../api/Azure.Communication.Sms.net8.0.cs | 30 ++- .../Azure.Communication.Sms.netstandard2.0.cs | 30 ++- .../Azure.Communication.Sms/assets.json | 2 +- .../src/Models/OptOutAddResponse.cs | 33 +++ .../src/Models/OptOutAddResponseItem.cs | 41 +++ ...ngeResponse.cs => OptOutRemoveResponse.cs} | 14 +- ...nseItem.cs => OptOutRemoveResponseItem.cs} | 12 +- .../src/OptOutsClient.cs | 16 +- .../tests/OptOutsClientTest.cs | 24 +- .../tests/SmsClientLiveTests.cs | 234 ++++++++++++++++-- 11 files changed, 376 insertions(+), 72 deletions(-) create mode 100644 sdk/communication/Azure.Communication.Sms/src/Models/OptOutAddResponse.cs create mode 100644 sdk/communication/Azure.Communication.Sms/src/Models/OptOutAddResponseItem.cs rename sdk/communication/Azure.Communication.Sms/src/Models/{OptOutChangeResponse.cs => OptOutRemoveResponse.cs} (60%) rename sdk/communication/Azure.Communication.Sms/src/Models/{OptOutChangeResponseItem.cs => OptOutRemoveResponseItem.cs} (82%) diff --git a/sdk/communication/Azure.Communication.Sms/CHANGELOG.md b/sdk/communication/Azure.Communication.Sms/CHANGELOG.md index 19014fa9ff66e..553bb3f03edea 100644 --- a/sdk/communication/Azure.Communication.Sms/CHANGELOG.md +++ b/sdk/communication/Azure.Communication.Sms/CHANGELOG.md @@ -1,14 +1,12 @@ # Release History -## 1.1.0-beta.2 (Unreleased) +## 1.1.0-beta.2 ### Features Added - -### Breaking Changes - -### Bugs Fixed - -### Other Changes + - Added support for Opt Out Management Api to: + - Opt-out the recipient. + - Opt-in the recipient. + - Check if the recpient is opted-out or not. ## 1.1.0-beta.1 (2024-05-07) diff --git a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.net8.0.cs b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.net8.0.cs index ce2f3be00a9c7..4b6a05ccf5fca 100644 --- a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.net8.0.cs +++ b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.net8.0.cs @@ -3,12 +3,12 @@ namespace Azure.Communication.Sms public partial class OptOutsClient { protected OptOutsClient() { } - public virtual Azure.Response> Add(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual System.Threading.Tasks.Task>> AddAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response> Add(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task>> AddAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response> Check(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task>> CheckAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual Azure.Response> Remove(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual System.Threading.Tasks.Task>> RemoveAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response> Remove(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task>> RemoveAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } public partial class SmsClient { @@ -56,13 +56,13 @@ public static partial class CommunicationSmsModelFactory public static Azure.Communication.Sms.Models.OptOutResponse OptOutResponse(System.Collections.Generic.IEnumerable value = null) { throw null; } public static Azure.Communication.Sms.Models.OptOutResponseItem OptOutResponseItem(string to = null, int httpStatusCode = 0, bool? isOptedOut = default(bool?), string errorMessage = null) { throw null; } } - public partial class OptOutChangeResponse + public partial class OptOutAddResponse { - internal OptOutChangeResponse() { } - public System.Collections.Generic.IReadOnlyList Value { get { throw null; } } + internal OptOutAddResponse() { } + public System.Collections.Generic.IReadOnlyList Value { get { throw null; } } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public partial struct OptOutChangeResponseItem + public partial struct OptOutAddResponseItem { private object _dummy; private int _dummyPrimitive; @@ -75,6 +75,20 @@ public partial class OptOutRecipient public OptOutRecipient(string to) { } public string To { get { throw null; } } } + public partial class OptOutRemoveResponse + { + internal OptOutRemoveResponse() { } + public System.Collections.Generic.IReadOnlyList Value { get { throw null; } } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public partial struct OptOutRemoveResponseItem + { + private object _dummy; + private int _dummyPrimitive; + public string ErrorMessage { get { throw null; } } + public int HttpStatusCode { get { throw null; } } + public string To { get { throw null; } } + } public partial class OptOutResponse { internal OptOutResponse() { } diff --git a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs index ce2f3be00a9c7..4b6a05ccf5fca 100644 --- a/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs +++ b/sdk/communication/Azure.Communication.Sms/api/Azure.Communication.Sms.netstandard2.0.cs @@ -3,12 +3,12 @@ namespace Azure.Communication.Sms public partial class OptOutsClient { protected OptOutsClient() { } - public virtual Azure.Response> Add(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual System.Threading.Tasks.Task>> AddAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response> Add(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task>> AddAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response> Check(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task>> CheckAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual Azure.Response> Remove(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public virtual System.Threading.Tasks.Task>> RemoveAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response> Remove(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task>> RemoveAsync(string from, System.Collections.Generic.IEnumerable to, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } public partial class SmsClient { @@ -56,13 +56,13 @@ public static partial class CommunicationSmsModelFactory public static Azure.Communication.Sms.Models.OptOutResponse OptOutResponse(System.Collections.Generic.IEnumerable value = null) { throw null; } public static Azure.Communication.Sms.Models.OptOutResponseItem OptOutResponseItem(string to = null, int httpStatusCode = 0, bool? isOptedOut = default(bool?), string errorMessage = null) { throw null; } } - public partial class OptOutChangeResponse + public partial class OptOutAddResponse { - internal OptOutChangeResponse() { } - public System.Collections.Generic.IReadOnlyList Value { get { throw null; } } + internal OptOutAddResponse() { } + public System.Collections.Generic.IReadOnlyList Value { get { throw null; } } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public partial struct OptOutChangeResponseItem + public partial struct OptOutAddResponseItem { private object _dummy; private int _dummyPrimitive; @@ -75,6 +75,20 @@ public partial class OptOutRecipient public OptOutRecipient(string to) { } public string To { get { throw null; } } } + public partial class OptOutRemoveResponse + { + internal OptOutRemoveResponse() { } + public System.Collections.Generic.IReadOnlyList Value { get { throw null; } } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public partial struct OptOutRemoveResponseItem + { + private object _dummy; + private int _dummyPrimitive; + public string ErrorMessage { get { throw null; } } + public int HttpStatusCode { get { throw null; } } + public string To { get { throw null; } } + } public partial class OptOutResponse { internal OptOutResponse() { } diff --git a/sdk/communication/Azure.Communication.Sms/assets.json b/sdk/communication/Azure.Communication.Sms/assets.json index 15352d38fbd30..e7fa3f54c5b53 100644 --- a/sdk/communication/Azure.Communication.Sms/assets.json +++ b/sdk/communication/Azure.Communication.Sms/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "net", "TagPrefix": "net/communication/Azure.Communication.Sms", - "Tag": "net/communication/Azure.Communication.Sms_363bacad7d" + "Tag": "net/communication/Azure.Communication.Sms_b96598d9ba" } diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/OptOutAddResponse.cs b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutAddResponse.cs new file mode 100644 index 0000000000000..f6b7b7e0cf269 --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutAddResponse.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Communication.Sms.Models +{ + /// Response for add opt out request. Validate the returned items in the response to see which recipients were successfully added to the opt outs list. + public partial class OptOutAddResponse + { + /// Initializes a new instance of . + /// + /// is null. + internal OptOutAddResponse(IEnumerable value) + { + Argument.AssertNotNull(value, nameof(value)); + + Value = value.ToList(); + } + + /// Initializes a new instance of . + /// + internal OptOutAddResponse(IReadOnlyList value) + { + Value = value; + } + + /// Gets the value. + public IReadOnlyList Value { get; } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/OptOutAddResponseItem.cs b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutAddResponseItem.cs new file mode 100644 index 0000000000000..ee9081eccbcb7 --- /dev/null +++ b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutAddResponseItem.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.Communication.Sms.Models +{ + /// The OptOutAddResponseItem. + public struct OptOutAddResponseItem + { + /// Initializes a new instance of . + /// The recipient phone number (in E.164 format). + /// + /// is null. + internal OptOutAddResponseItem(string to, int httpStatusCode) + { + Argument.AssertNotNull(to, nameof(to)); + + To = to; + HttpStatusCode = httpStatusCode; + } + + /// Initializes a new instance of . + /// The recipient phone number (in E.164 format). + /// + /// Optional error message in case of 4xx/5xx errors. + internal OptOutAddResponseItem(string to, int httpStatusCode, string errorMessage) + { + To = to; + HttpStatusCode = httpStatusCode; + ErrorMessage = errorMessage; + } + + /// The recipient phone number (in E.164 format). + public string To { get; } + /// Gets the http status code. + public int HttpStatusCode { get; } + /// Optional error message in case of 4xx/5xx errors. + public string ErrorMessage { get; } + } +} diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponse.cs b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutRemoveResponse.cs similarity index 60% rename from sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponse.cs rename to sdk/communication/Azure.Communication.Sms/src/Models/OptOutRemoveResponse.cs index b555150e69ee4..5a31d89078401 100644 --- a/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponse.cs +++ b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutRemoveResponse.cs @@ -7,27 +7,27 @@ namespace Azure.Communication.Sms.Models { - /// Response for an add and remove opt out request. Validate the returned items in the response to see which recipients were successfully added or removed from the opt outs list. - public partial class OptOutChangeResponse + /// Response for remove opt out request. Validate the returned items in the response to see which recipients were successfully removed from the opt outs list. + public partial class OptOutRemoveResponse { - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// is null. - internal OptOutChangeResponse(IEnumerable value) + internal OptOutRemoveResponse(IEnumerable value) { Argument.AssertNotNull(value, nameof(value)); Value = value.ToList(); } - /// Initializes a new instance of . + /// Initializes a new instance of . /// - internal OptOutChangeResponse(IReadOnlyList value) + internal OptOutRemoveResponse(IReadOnlyList value) { Value = value; } /// Gets the value. - public IReadOnlyList Value { get; } + public IReadOnlyList Value { get; } } } diff --git a/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponseItem.cs b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutRemoveResponseItem.cs similarity index 82% rename from sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponseItem.cs rename to sdk/communication/Azure.Communication.Sms/src/Models/OptOutRemoveResponseItem.cs index 9b4c911377268..f987e9fd20104 100644 --- a/sdk/communication/Azure.Communication.Sms/src/Models/OptOutChangeResponseItem.cs +++ b/sdk/communication/Azure.Communication.Sms/src/Models/OptOutRemoveResponseItem.cs @@ -5,14 +5,14 @@ namespace Azure.Communication.Sms.Models { - /// The OptOutChangeResponseItem. - public struct OptOutChangeResponseItem + /// The OptOutRemoveResponseItem. + public struct OptOutRemoveResponseItem { - /// Initializes a new instance of . + /// Initializes a new instance of . /// The recipient phone number (in E.164 format). /// /// is null. - internal OptOutChangeResponseItem(string to, int httpStatusCode) + internal OptOutRemoveResponseItem(string to, int httpStatusCode) { Argument.AssertNotNull(to, nameof(to)); @@ -20,11 +20,11 @@ internal OptOutChangeResponseItem(string to, int httpStatusCode) HttpStatusCode = httpStatusCode; } - /// Initializes a new instance of . + /// Initializes a new instance of . /// The recipient phone number (in E.164 format). /// /// Optional error message in case of 4xx/5xx errors. - internal OptOutChangeResponseItem(string to, int httpStatusCode, string errorMessage) + internal OptOutRemoveResponseItem(string to, int httpStatusCode, string errorMessage) { To = to; HttpStatusCode = httpStatusCode; diff --git a/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs b/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs index c62bb86500229..bcd636c8c3398 100644 --- a/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs +++ b/sdk/communication/Azure.Communication.Sms/src/OptOutsClient.cs @@ -106,7 +106,7 @@ public virtual Response> Check(string from, IE /// The server returned an error. See for details returned from the server. /// is null. /// is null. - public virtual async Task>> AddAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) + public virtual async Task>> AddAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(OptOutsClient)}.{nameof(Add)}"); scope.Start(); @@ -117,7 +117,7 @@ public virtual async Task>> Add IEnumerable recipients = to.Select(x => new OptOutRecipient(Argument.CheckNotNullOrEmpty(x, nameof(to)))); Response response = await OptOutsRestClient.AddAsync(from, recipients, cancellationToken).ConfigureAwait(false); - OptOutChangeResponse result = new OptOutChangeResponse(response.Value.Value.Select(r => new OptOutChangeResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); + OptOutAddResponse result = new OptOutAddResponse(response.Value.Value.Select(r => new OptOutAddResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); return Response.FromValue(result.Value, response.GetRawResponse()); } @@ -137,7 +137,7 @@ public virtual async Task>> Add /// The server returned an error. See for details returned from the server. /// is null. /// is null. - public virtual Response> Add(string from, IEnumerable to, CancellationToken cancellationToken = default) + public virtual Response> Add(string from, IEnumerable to, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(OptOutsClient)}.{nameof(Add)}"); scope.Start(); @@ -148,7 +148,7 @@ public virtual Response> Add(string from IEnumerable recipients = to.Select(x => new OptOutRecipient(Argument.CheckNotNullOrEmpty(x, nameof(to)))); Response response = OptOutsRestClient.Add(from, recipients, cancellationToken); - OptOutChangeResponse result = new OptOutChangeResponse(response.Value.Value.Select(r => new OptOutChangeResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); + OptOutAddResponse result = new OptOutAddResponse(response.Value.Value.Select(r => new OptOutAddResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); return Response.FromValue(result.Value, response.GetRawResponse()); } @@ -168,7 +168,7 @@ public virtual Response> Add(string from /// The server returned an error. See for details returned from the server. /// is null. /// is null. - public virtual async Task>> RemoveAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) + public virtual async Task>> RemoveAsync(string from, IEnumerable to, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(OptOutsClient)}.{nameof(Remove)}"); scope.Start(); @@ -179,7 +179,7 @@ public virtual async Task>> Rem IEnumerable recipients = to.Select(x => new OptOutRecipient(Argument.CheckNotNullOrEmpty(x, nameof(to)))); Response response = await OptOutsRestClient.RemoveAsync(from, recipients, cancellationToken).ConfigureAwait(false); - OptOutChangeResponse result = new OptOutChangeResponse(response.Value.Value.Select(r => new OptOutChangeResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); + OptOutRemoveResponse result = new OptOutRemoveResponse(response.Value.Value.Select(r => new OptOutRemoveResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); return Response.FromValue(result.Value, response.GetRawResponse()); } @@ -199,7 +199,7 @@ public virtual async Task>> Rem /// The server returned an error. See for details returned from the server. /// is null. /// is null. - public virtual Response> Remove(string from, IEnumerable to, CancellationToken cancellationToken = default) + public virtual Response> Remove(string from, IEnumerable to, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(OptOutsClient)}.{nameof(Remove)}"); scope.Start(); @@ -210,7 +210,7 @@ public virtual Response> Remove(string f IEnumerable recipients = to.Select(x => new OptOutRecipient(Argument.CheckNotNullOrEmpty(x, nameof(to)))); Response response = OptOutsRestClient.Remove(from, recipients, cancellationToken); - OptOutChangeResponse result = new OptOutChangeResponse(response.Value.Value.Select(r => new OptOutChangeResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); + OptOutRemoveResponse result = new OptOutRemoveResponse(response.Value.Value.Select(r => new OptOutRemoveResponseItem(r.To, r.HttpStatusCode, r.ErrorMessage))); return Response.FromValue(result.Value, response.GetRawResponse()); } diff --git a/sdk/communication/Azure.Communication.Sms/tests/OptOutsClientTest.cs b/sdk/communication/Azure.Communication.Sms/tests/OptOutsClientTest.cs index 509d00d6250d0..6769c805ca44d 100644 --- a/sdk/communication/Azure.Communication.Sms/tests/OptOutsClientTest.cs +++ b/sdk/communication/Azure.Communication.Sms/tests/OptOutsClientTest.cs @@ -94,7 +94,7 @@ public void CheckOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable< public async Task AddAsyncOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) { Mock mockClient = new Mock() { CallBase = true }; - Response>? expectedResponse = default; + Response>? expectedResponse = default; CancellationToken cancellationToken = new CancellationTokenSource().Token; var callExpression = BuildExpression(x => x.AddAsync(It.IsAny(), It.IsAny>(), It.IsAny())); @@ -105,10 +105,10 @@ public async Task AddAsyncOverload_PassesToGeneratedOne(string expectedFrom, IEn Assert.AreEqual(expectedFrom, from); Assert.AreEqual(expectedTo, to); Assert.AreEqual(cancellationToken, token); - return expectedResponse = new Mock>>().Object; + return expectedResponse = new Mock>>().Object; }); - Response> actualResponse = await mockClient.Object.AddAsync(expectedFrom, expectedTo, cancellationToken); + Response> actualResponse = await mockClient.Object.AddAsync(expectedFrom, expectedTo, cancellationToken); mockClient.Verify(callExpression, Times.Once()); Assert.AreEqual(expectedResponse, actualResponse); @@ -118,7 +118,7 @@ public async Task AddAsyncOverload_PassesToGeneratedOne(string expectedFrom, IEn public void AddOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) { Mock mockClient = new Mock() { CallBase = true }; - Response>? expectedResponse = default; + Response>? expectedResponse = default; CancellationToken cancellationToken = new CancellationTokenSource().Token; var callExpression = BuildExpression(x => x.Add(It.IsAny(), It.IsAny>(), It.IsAny())); @@ -129,10 +129,10 @@ public void AddOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable>>().Object; + return expectedResponse = new Mock>>().Object; }); - Response> actualResponse = mockClient.Object.Add(expectedFrom, expectedTo, cancellationToken); + Response> actualResponse = mockClient.Object.Add(expectedFrom, expectedTo, cancellationToken); mockClient.Verify(callExpression, Times.Once()); Assert.AreEqual(expectedResponse, actualResponse); @@ -142,7 +142,7 @@ public void AddOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) { Mock mockClient = new Mock() { CallBase = true }; - Response>? expectedResponse = default; + Response>? expectedResponse = default; CancellationToken cancellationToken = new CancellationTokenSource().Token; var callExpression = BuildExpression(x => x.RemoveAsync(It.IsAny(), It.IsAny>(), It.IsAny())); @@ -153,10 +153,10 @@ public async Task RemoveAsyncOverload_PassesToGeneratedOne(string expectedFrom, Assert.AreEqual(expectedFrom, from); Assert.AreEqual(expectedTo, to); Assert.AreEqual(cancellationToken, token); - return expectedResponse = new Mock>>().Object; + return expectedResponse = new Mock>>().Object; }); - Response> actualResponse = await mockClient.Object.RemoveAsync(expectedFrom, expectedTo, cancellationToken); + Response> actualResponse = await mockClient.Object.RemoveAsync(expectedFrom, expectedTo, cancellationToken); mockClient.Verify(callExpression, Times.Once()); Assert.AreEqual(expectedResponse, actualResponse); @@ -166,7 +166,7 @@ public async Task RemoveAsyncOverload_PassesToGeneratedOne(string expectedFrom, public void RemoveOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable expectedTo) { Mock mockClient = new Mock() { CallBase = true }; - Response>? expectedResponse = default; + Response>? expectedResponse = default; CancellationToken cancellationToken = new CancellationTokenSource().Token; var callExpression = BuildExpression(x => x.Remove(It.IsAny(), It.IsAny>(), It.IsAny())); @@ -177,10 +177,10 @@ public void RemoveOverload_PassesToGeneratedOne(string expectedFrom, IEnumerable Assert.AreEqual(expectedFrom, from); Assert.AreEqual(expectedTo, to); Assert.AreEqual(cancellationToken, token); - return expectedResponse = new Mock>>().Object; + return expectedResponse = new Mock>>().Object; }); - Response> actualResponse = mockClient.Object.Remove(expectedFrom, expectedTo, cancellationToken); + Response> actualResponse = mockClient.Object.Remove(expectedFrom, expectedTo, cancellationToken); mockClient.Verify(callExpression, Times.Once()); Assert.AreEqual(expectedResponse, actualResponse); diff --git a/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTests.cs b/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTests.cs index 85c7cd0727a8b..3173643192969 100644 --- a/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTests.cs +++ b/sdk/communication/Azure.Communication.Sms/tests/SmsClientLiveTests.cs @@ -104,7 +104,7 @@ public async Task SendingSmsMessageToGroupWithOptions() { var response = await client.SendAsync( from: TestEnvironment.FromPhoneNumber, - to: new string[] { TestEnvironment.ToPhoneNumber, TestEnvironment.ToPhoneNumber }, + to: [TestEnvironment.ToPhoneNumber, TestEnvironment.ToPhoneNumber], message: "Hi", options: new SmsSendOptions(enableDeliveryReport: true) // OPTIONAL { @@ -210,7 +210,7 @@ public async Task CheckOptOutFromNullNumberShouldThrow() SmsClient client = CreateSmsClient(); try { - IEnumerable? to = new string[] { TestEnvironment.ToPhoneNumber }; + IEnumerable? to = [TestEnvironment.ToPhoneNumber]; Response> result = await client.OptOuts.CheckAsync( from: null, to: to); @@ -249,11 +249,11 @@ public async Task CheckOptOutToCollectionContainingNullShouldThrow() try { #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. - IEnumerable? to = new string[] - { + IEnumerable? to = + [ TestEnvironment.ToPhoneNumber, null - }; + ]; #pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. Response> result = await client.OptOuts.CheckAsync( @@ -268,15 +268,206 @@ public async Task CheckOptOutToCollectionContainingNullShouldThrow() Assert.Fail("CheckAsync should have thrown an exception."); } + [Test] + public async Task CheckOptOutToInvalidNumberShouldThrow() + { + SmsClient client = CreateSmsClient(); + + try + { + IEnumerable? to = ["+15550000000"]; + Response> result = await client.OptOuts.CheckAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + } + catch (RequestFailedException ex) + { + Assert.That(ex.Message.Contains("InvalidInput")); + return; + } + + Assert.Fail("CheckAsync should have thrown an exception."); + } + + [Test] + public async Task AddOptOutFromNullNumberShouldThrow() + { + SmsClient client = CreateSmsClient(); + try + { + IEnumerable? to = [TestEnvironment.ToPhoneNumber]; + Response> result = await client.OptOuts.AddAsync( + from: null, + to: to); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("from", ex.ParamName); + return; + } + Assert.Fail("AddAsync should have thrown an exception."); + } + + [Test] + public async Task AddOptOutToNullNumberShouldThrow() + { + SmsClient client = CreateSmsClient(); + try + { + IEnumerable? to = null; + Response> result = await client.OptOuts.AddAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("to", ex.ParamName); + return; + } + Assert.Fail("AddAsync should have thrown an exception."); + } + + [Test] + public async Task AddOptOutToCollectionContainingNullShouldThrow() + { + SmsClient client = CreateSmsClient(); + try + { +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. + IEnumerable? to = + [ + TestEnvironment.ToPhoneNumber, + null + ]; +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. + + Response> result = await client.OptOuts.AddAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("to", ex.ParamName); + return; + } + Assert.Fail("AddAsync should have thrown an exception."); + } + + [Test] + public async Task AddOptOutToInvalidNumberShouldThrow() + { + SmsClient client = CreateSmsClient(); + + try + { + IEnumerable? to = ["+15550000000"]; + Response> result = await client.OptOuts.AddAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + } + catch (RequestFailedException ex) + { + Assert.That(ex.Message.Contains("InvalidInput")); + return; + } + + Assert.Fail("AddAsync should have thrown an exception."); + } + + [Test] + public async Task RemoveOptOutFromNullNumberShouldThrow() + { + SmsClient client = CreateSmsClient(); + try + { + IEnumerable? to = [TestEnvironment.ToPhoneNumber]; + Response> result = await client.OptOuts.RemoveAsync( + from: null, + to: to); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("from", ex.ParamName); + return; + } + Assert.Fail("RemoveAsync should have thrown an exception."); + } + + [Test] + public async Task RemoveOptOutToNullNumberShouldThrow() + { + SmsClient client = CreateSmsClient(); + try + { + IEnumerable? to = null; + Response> result = await client.OptOuts.RemoveAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("to", ex.ParamName); + return; + } + Assert.Fail("RemoveAsync should have thrown an exception."); + } + + [Test] + public async Task RemoveOptOutToCollectionContainingNullShouldThrow() + { + SmsClient client = CreateSmsClient(); + try + { +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. + IEnumerable? to = + [ + TestEnvironment.ToPhoneNumber, + null + ]; +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. + + Response> result = await client.OptOuts.RemoveAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + } + catch (ArgumentNullException ex) + { + Assert.AreEqual("to", ex.ParamName); + return; + } + Assert.Fail("RemoveAsync should have thrown an exception."); + } + + [Test] + public async Task RemoveOptOutToInvalidNumberShouldThrow() + { + SmsClient client = CreateSmsClient(); + + try + { + IEnumerable? to = ["+15550000000"]; + Response> result = await client.OptOuts.RemoveAsync( + from: TestEnvironment.FromPhoneNumber, + to: to); + } + catch (RequestFailedException ex) + { + Assert.That(ex.Message.Contains("InvalidInput")); + return; + } + + Assert.Fail("RemoveAsync should have thrown an exception."); + } + [Test] public async Task AddOptOutEndpointShouldMarkRecipientAsOptedOut() { SmsClient client = CreateSmsClient(); try { - IEnumerable? to = new[] { TestEnvironment.ToPhoneNumber }; + IEnumerable? to = [TestEnvironment.ToPhoneNumber]; - Response> addResult = await client.OptOuts.AddAsync( + Response> addResult = await client.OptOuts.AddAsync( from: TestEnvironment.FromPhoneNumber, to: to); @@ -300,13 +491,13 @@ public async Task RemoveOptOutEndpointShouldMarkRecipientAsOptedIn() SmsClient client = CreateSmsClient(); try { - IEnumerable? to = new[] { TestEnvironment.ToPhoneNumber }; + IEnumerable? to = [TestEnvironment.ToPhoneNumber]; - Response> addResult = await client.OptOuts.AddAsync( + Response> addResult = await client.OptOuts.AddAsync( from: TestEnvironment.FromPhoneNumber, to: to); - Response> removeResult = await client.OptOuts.RemoveAsync( + Response> removeResult = await client.OptOuts.RemoveAsync( from: TestEnvironment.FromPhoneNumber, to: to); @@ -330,9 +521,9 @@ public async Task AddOptOutEndpointShouldMarkRecipientsAsOptedOut() SmsClient client = CreateSmsClient(); try { - IEnumerable? to = new[] { TestEnvironment.ToPhoneNumber, TestEnvironment.ToPhoneNumber }; + IEnumerable? to = [TestEnvironment.ToPhoneNumber, TestEnvironment.ToPhoneNumber]; - Response> addResult = await client.OptOuts.AddAsync( + Response> addResult = await client.OptOuts.AddAsync( from: TestEnvironment.FromPhoneNumber, to: to); @@ -357,13 +548,13 @@ public async Task RemoveOptOutEndpointShouldMarkRecipientsAsOptedIn() SmsClient client = CreateSmsClient(); try { - IEnumerable? to = new[] { TestEnvironment.ToPhoneNumber, TestEnvironment.ToPhoneNumber }; + IEnumerable? to = [TestEnvironment.ToPhoneNumber, TestEnvironment.ToPhoneNumber]; - Response> addResult = await client.OptOuts.AddAsync( + Response> addResult = await client.OptOuts.AddAsync( from: TestEnvironment.FromPhoneNumber, to: to); - Response> removeResult = await client.OptOuts.RemoveAsync( + Response> removeResult = await client.OptOuts.RemoveAsync( from: TestEnvironment.FromPhoneNumber, to: to); @@ -400,5 +591,18 @@ private void AssertSmsSendingRawResponseHappyPath(Stream contentStream) } Assert.Fail("Response content stream is empty."); } + + private void AssertOptOutRawResponseBadRequest(Stream contentStream) + { + if (contentStream.Length > 0) + { + StreamReader streamReader = new StreamReader(contentStream); + streamReader.BaseStream.Seek(0, SeekOrigin.Begin); + string rawResponse = streamReader.ReadToEnd(); + Assert.True(rawResponse.Contains("\"code\":\"InvalidInput\"")); + return; + } + Assert.Fail("Response content stream is empty."); + } } } From ce7450f87563d6ed19e6b56a57b66b701ce87459 Mon Sep 17 00:00:00 2001 From: FarhadJabiyev Date: Thu, 28 Nov 2024 22:01:00 +0200 Subject: [PATCH 9/9] Set changelog date --- sdk/communication/Azure.Communication.Sms/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/communication/Azure.Communication.Sms/CHANGELOG.md b/sdk/communication/Azure.Communication.Sms/CHANGELOG.md index 553bb3f03edea..148666459c57a 100644 --- a/sdk/communication/Azure.Communication.Sms/CHANGELOG.md +++ b/sdk/communication/Azure.Communication.Sms/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 1.1.0-beta.2 +## 1.1.0-beta.2 (2024-12-10) ### Features Added - Added support for Opt Out Management Api to: