diff --git a/Libraries/Microsoft.Teams.Api/Clients/ApiClient.cs b/Libraries/Microsoft.Teams.Api/Clients/ApiClient.cs index 0c2f04ec..b1588d2a 100644 --- a/Libraries/Microsoft.Teams.Api/Clients/ApiClient.cs +++ b/Libraries/Microsoft.Teams.Api/Clients/ApiClient.cs @@ -14,6 +14,18 @@ public class ApiClient : Client public virtual TeamClient Teams { get; } public virtual MeetingClient Meetings { get; } + /// + /// Gets the underlying instance used by this + /// and its sub-clients to perform HTTP requests. + /// + /// + /// This property is provided for advanced scenarios where you need to issue custom HTTP + /// calls that are not yet covered by the strongly-typed clients exposed by . + /// Prefer using the typed clients (, , + /// , , ) whenever possible. + /// Relying on this property may couple your code to the current HTTP implementation and + /// could limit future refactoring of the underlying client. + /// public IHttpClient Client { get => base._http; } public ApiClient(string serviceUrl, CancellationToken cancellationToken = default) : base(cancellationToken) @@ -34,7 +46,6 @@ public ApiClient(string serviceUrl, IHttpClient client, CancellationToken cancel Users = new UserClient(_http, cancellationToken); Teams = new TeamClient(serviceUrl, _http, cancellationToken); Meetings = new MeetingClient(serviceUrl, _http, cancellationToken); - } public ApiClient(string serviceUrl, IHttpClientOptions options, CancellationToken cancellationToken = default) : base(options, cancellationToken) diff --git a/Libraries/Microsoft.Teams.Api/Clients/ReactionClient.cs b/Libraries/Microsoft.Teams.Api/Clients/ReactionClient.cs index 5759d686..ea166991 100644 --- a/Libraries/Microsoft.Teams.Api/Clients/ReactionClient.cs +++ b/Libraries/Microsoft.Teams.Api/Clients/ReactionClient.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using Microsoft.Teams.Api.Messages; @@ -45,11 +45,8 @@ public ReactionClient(string serviceUrl, IHttpClientFactory factory, Cancellatio /// /// The reaction type (for example: "like", "heart", "laugh", etc.). /// - /// - /// Optional id of the user on whose behalf the reaction is added/updated (if supported by the service). - /// /// - /// A describing the reaction, or null if the service returned an empty body. + /// A representing the asynchronous operation. /// public async Task CreateOrUpdateAsync( string conversationId, @@ -72,9 +69,9 @@ ReactionType reactionType /// /// The reaction type to remove (for example: "like", "heart", "laugh", etc.). /// - /// - /// Optional id of the user whose reaction should be removed (if supported by the service). - /// + /// + /// A representing the asynchronous operation. + /// public async Task DeleteAsync( string conversationId, string activityId, diff --git a/Libraries/Microsoft.Teams.Api/Messages/Reaction.cs b/Libraries/Microsoft.Teams.Api/Messages/Reaction.cs index ec8613c5..1bbb568b 100644 --- a/Libraries/Microsoft.Teams.Api/Messages/Reaction.cs +++ b/Libraries/Microsoft.Teams.Api/Messages/Reaction.cs @@ -8,7 +8,7 @@ namespace Microsoft.Teams.Api.Messages; /// -/// The type of reaction given to the +/// The type of reaction given to the message. /// [JsonConverter(typeof(JsonConverter))] public class ReactionType(string value) : StringEnum(value) diff --git a/Samples/Samples.Reactions/Program.cs b/Samples/Samples.Reactions/Program.cs index 7b25d830..20be7dc7 100644 --- a/Samples/Samples.Reactions/Program.cs +++ b/Samples/Samples.Reactions/Program.cs @@ -32,7 +32,7 @@ teams.OnMessageReaction(async (context, cancellationToken) => { context.Log.Info($"Reaction '{context.Activity.ReactionsAdded?.FirstOrDefault()?.Type}' added by {context.Activity.From?.Name}"); - await context.Send($"you reacted with added '{context.Activity.ReactionsAdded?.FirstOrDefault()?.Type}' " + + await context.Send($"you added '{context.Activity.ReactionsAdded?.FirstOrDefault()?.Type}' " + $"and removed '{context.Activity.ReactionsRemoved?.FirstOrDefault()?.Type}'", cancellationToken); }); diff --git a/Tests/Microsoft.Teams.Api.Tests/Clients/ReactionClientTests.cs b/Tests/Microsoft.Teams.Api.Tests/Clients/ReactionClientTests.cs new file mode 100644 index 00000000..cef8b1f8 --- /dev/null +++ b/Tests/Microsoft.Teams.Api.Tests/Clients/ReactionClientTests.cs @@ -0,0 +1,74 @@ +using System.Net; + +using Microsoft.Teams.Api.Clients; +using Microsoft.Teams.Api.Messages; +using Microsoft.Teams.Common.Http; + +using Moq; + +namespace Microsoft.Teams.Api.Tests.Clients; + +public class ReactionClientTests +{ + [Fact] + public async Task ReactionClient_CreateOrUpdateAsync() + { + var responseMessage = new HttpResponseMessage(); + responseMessage.Headers.Add("Custom-Header", "HeaderValue"); + var mockHandler = new Mock(); + mockHandler + .Setup(handler => handler.SendAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new HttpResponse() + { + Headers = responseMessage.Headers, + StatusCode = HttpStatusCode.OK, + Body = string.Empty + }); + + string serviceUrl = "https://serviceurl.com/"; + var reactionClient = new ReactionClient(serviceUrl, mockHandler.Object); + string conversationId = "conversationId"; + string activityId = "activityId"; + var reactionType = ReactionType.Like; + + await reactionClient.CreateOrUpdateAsync(conversationId, activityId, reactionType); + + string expectedUrl = "https://serviceurl.com/v3/conversations/conversationId/activities/activityId/reactions/like"; + HttpMethod expectedMethod = HttpMethod.Put; + mockHandler.Verify(x => x.SendAsync( + It.Is(arg => arg.Url == expectedUrl && arg.Method == expectedMethod), + It.IsAny()), + Times.Once); + } + + [Fact] + public async Task ReactionClient_DeleteAsync() + { + var responseMessage = new HttpResponseMessage(); + responseMessage.Headers.Add("Custom-Header", "HeaderValue"); + var mockHandler = new Mock(); + mockHandler + .Setup(handler => handler.SendAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new HttpResponse() + { + Headers = responseMessage.Headers, + StatusCode = HttpStatusCode.OK, + Body = string.Empty + }); + + string serviceUrl = "https://serviceurl.com/"; + var reactionClient = new ReactionClient(serviceUrl, mockHandler.Object); + string conversationId = "conversationId"; + string activityId = "activityId"; + var reactionType = ReactionType.Heart; + + await reactionClient.DeleteAsync(conversationId, activityId, reactionType); + + string expectedUrl = "https://serviceurl.com/v3/conversations/conversationId/activities/activityId/reactions/heart"; + HttpMethod expectedMethod = HttpMethod.Delete; + mockHandler.Verify(x => x.SendAsync( + It.Is(arg => arg.Url == expectedUrl && arg.Method == expectedMethod), + It.IsAny()), + Times.Once); + } +}