microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
3ddf9fa76ec1801a0e3ca312c6d9855879571ac1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

core/test/Microsoft.Teams.Apps.BotBuilder.UnitTests/CompatBotAdapterTests.cs

332lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using Microsoft.AspNetCore.Http;
5using Microsoft.Bot.Builder;
6using Microsoft.Bot.Schema;
7using Microsoft.Extensions.Logging.Abstractions;
8using Microsoft.Teams.Apps;
9using Microsoft.Teams.Apps.Api.Clients;
10using Microsoft.Teams.Core;
11using Microsoft.Teams.Core.Schema;
12using Moq;
13
14namespace Microsoft.Teams.Apps.BotBuilder.UnitTests
15{
16 public class TeamsBotAdapterTests
17 {
18 [Fact]
19 public async Task DeleteActivityAsync_UsesConversationReferenceValues()
20 {
21 // Arrange
22 Mock<ConversationClient> mockConversationClient = CreateMockConversationClient();
23 TeamsBotAdapter adapter = CreateCompatBotAdapter(mockConversationClient.Object);
24
25 ConversationReference reference = new()
26 {
27 ActivityId = "activity-123",
28 ServiceUrl = "https://smba.trafficmanager.net/teams/",
29 Conversation = new Microsoft.Bot.Schema.ConversationAccount { Id = "conversation-456" },
30 ChannelId = "msteams"
31 };
32
33 ITurnContext turnContext = CreateMockTurnContext("https://different-service-url.com/");
34
35 // Act
36 await adapter.DeleteActivityAsync(turnContext, reference, CancellationToken.None);
37
38 // Assert
39 mockConversationClient.Verify(
40 c => c.DeleteActivityAsync(
41 "conversation-456",
42 "activity-123",
43 It.Is<Uri>(u => u.ToString().TrimEnd('/') == "https://smba.trafficmanager.net/teams"),
44 It.IsAny<AgenticIdentity>(),
45 null,
46 It.IsAny<CancellationToken>()),
47 Times.Once);
48 }
49
50 [Fact]
51 public async Task DeleteActivityAsync_FallsBackToTurnContextServiceUrl_WhenReferenceServiceUrlIsNull()
52 {
53 // Arrange
54 Mock<ConversationClient> mockConversationClient = CreateMockConversationClient();
55 TeamsBotAdapter adapter = CreateCompatBotAdapter(mockConversationClient.Object);
56
57 ConversationReference reference = new()
58 {
59 ActivityId = "activity-123",
60 ServiceUrl = null, // Not set in reference
61 Conversation = new Microsoft.Bot.Schema.ConversationAccount { Id = "conversation-456" },
62 ChannelId = "msteams"
63 };
64
65 ITurnContext turnContext = CreateMockTurnContext("https://fallback-service-url.com/");
66
67 // Act
68 await adapter.DeleteActivityAsync(turnContext, reference, CancellationToken.None);
69
70 // Assert
71 mockConversationClient.Verify(
72 c => c.DeleteActivityAsync(
73 "conversation-456",
74 "activity-123",
75 It.Is<Uri>(u => u.ToString().TrimEnd('/') == "https://fallback-service-url.com"),
76 It.IsAny<AgenticIdentity>(),
77 null,
78 It.IsAny<CancellationToken>()),
79 Times.Once);
80 }
81
82 [Fact]
83 public async Task DeleteActivityAsync_ThrowsArgumentException_WhenConversationIdIsNull()
84 {
85 // Arrange
86 Mock<ConversationClient> mockConversationClient = CreateMockConversationClient();
87 TeamsBotAdapter adapter = CreateCompatBotAdapter(mockConversationClient.Object);
88
89 ConversationReference reference = new()
90 {
91 ActivityId = "activity-123",
92 ServiceUrl = "https://smba.trafficmanager.net/teams/",
93 Conversation = null, // No conversation
94 ChannelId = "msteams"
95 };
96
97 ITurnContext turnContext = CreateMockTurnContext("https://service-url.com/");
98
99 // Act & Assert
100 await Assert.ThrowsAsync<ArgumentException>(
101 async () => await adapter.DeleteActivityAsync(turnContext, reference, CancellationToken.None));
102 }
103
104 [Fact]
105 public async Task DeleteActivityAsync_ThrowsArgumentException_WhenActivityIdIsNull()
106 {
107 // Arrange
108 Mock<ConversationClient> mockConversationClient = CreateMockConversationClient();
109 TeamsBotAdapter adapter = CreateCompatBotAdapter(mockConversationClient.Object);
110
111 ConversationReference reference = new()
112 {
113 ActivityId = null, // No activity ID
114 ServiceUrl = "https://smba.trafficmanager.net/teams/",
115 Conversation = new Microsoft.Bot.Schema.ConversationAccount { Id = "conversation-456" },
116 ChannelId = "msteams"
117 };
118
119 ITurnContext turnContext = CreateMockTurnContext("https://service-url.com/");
120
121 // Act & Assert
122 await Assert.ThrowsAsync<ArgumentException>(
123 async () => await adapter.DeleteActivityAsync(turnContext, reference, CancellationToken.None));
124 }
125
126 [Fact]
127 public async Task DeleteActivityAsync_ThrowsArgumentException_WhenServiceUrlIsNull()
128 {
129 // Arrange
130 Mock<ConversationClient> mockConversationClient = CreateMockConversationClient();
131 TeamsBotAdapter adapter = CreateCompatBotAdapter(mockConversationClient.Object);
132
133 ConversationReference reference = new()
134 {
135 ActivityId = "activity-123",
136 ServiceUrl = null, // No service URL in reference
137 Conversation = new Microsoft.Bot.Schema.ConversationAccount { Id = "conversation-456" },
138 ChannelId = "msteams"
139 };
140
141 ITurnContext turnContext = CreateMockTurnContext(null); // No service URL in turn context either
142
143 // Act & Assert
144 await Assert.ThrowsAsync<ArgumentException>(
145 async () => await adapter.DeleteActivityAsync(turnContext, reference, CancellationToken.None));
146 }
147
148 [Fact]
149 public async Task SendActivitiesAsync_SetsServiceUrlFromTurnContext()
150 {
151 // Arrange
152 Mock<ConversationClient> mockConversationClient = CreateMockConversationClient();
153 mockConversationClient.Setup(c => c.SendActivityAsync(
154 It.IsAny<CoreActivity>(),
155 It.IsAny<Dictionary<string, string>?>(),
156 It.IsAny<CancellationToken>()))
157 .ReturnsAsync(new SendActivityResponse { Id = "sent-123" });
158
159 TeamsBotAdapter adapter = CreateCompatBotAdapter(mockConversationClient.Object);
160
161 Activity activity = new()
162 {
163 Type = ActivityTypes.Message,
164 Text = "Hello",
165 Conversation = new Microsoft.Bot.Schema.ConversationAccount { Id = "conversation-123" },
166 ServiceUrl = null // ServiceUrl not set on activity
167 };
168
169 ITurnContext turnContext = CreateMockTurnContext("https://turn-context-service-url.com/");
170
171 // Act
172 ResourceResponse[] responses = await adapter.SendActivitiesAsync(turnContext, [activity], CancellationToken.None);
173
174 // Assert
175 Assert.Single(responses);
176 Assert.Equal("sent-123", responses[0].Id);
177
178 mockConversationClient.Verify(
179 c => c.SendActivityAsync(
180 It.Is<CoreActivity>(a => a.ServiceUrl != null && a.ServiceUrl.ToString().TrimEnd('/') == "https://turn-context-service-url.com"),
181 It.IsAny<Dictionary<string, string>?>(),
182 It.IsAny<CancellationToken>()),
183 Times.Once);
184 }
185
186 [Fact]
187 public async Task UpdateActivityAsync_SetsServiceUrlFromTurnContext()
188 {
189 // Arrange
190 Mock<ConversationClient> mockConversationClient = CreateMockConversationClient();
191 mockConversationClient.Setup(c => c.UpdateActivityAsync(
192 It.IsAny<string>(),
193 It.IsAny<string>(),
194 It.IsAny<CoreActivity>(),
195 It.IsAny<bool>(),
196 It.IsAny<AgenticIdentity?>(),
197 It.IsAny<Dictionary<string, string>?>(),
198 It.IsAny<CancellationToken>()))
199 .ReturnsAsync(new UpdateActivityResponse { Id = "updated-123" });
200
201 TeamsBotAdapter adapter = CreateCompatBotAdapter(mockConversationClient.Object);
202
203 Activity activity = new()
204 {
205 Type = ActivityTypes.Message,
206 Id = "activity-123",
207 Text = "Updated message",
208 Conversation = new Microsoft.Bot.Schema.ConversationAccount { Id = "conversation-123" },
209 ServiceUrl = null // ServiceUrl not set on activity
210 };
211
212 ITurnContext turnContext = CreateMockTurnContext("https://turn-context-service-url.com/");
213
214 // Act
215 ResourceResponse response = await adapter.UpdateActivityAsync(turnContext, activity, CancellationToken.None);
216
217 // Assert
218 Assert.Equal("updated-123", response.Id);
219
220 mockConversationClient.Verify(
221 c => c.UpdateActivityAsync(
222 "conversation-123",
223 "activity-123",
224 It.Is<CoreActivity>(a => a.ServiceUrl != null && a.ServiceUrl.ToString().TrimEnd('/') == "https://turn-context-service-url.com"),
225 It.IsAny<bool>(),
226 It.IsAny<AgenticIdentity?>(),
227 It.IsAny<Dictionary<string, string>?>(),
228 It.IsAny<CancellationToken>()),
229 Times.Once);
230 }
231
232 private static Mock<ConversationClient> CreateMockConversationClient()
233 {
234 Mock<ConversationClient> mock = new(
235 new HttpClient(),
236 NullLogger<ConversationClient>.Instance);
237
238 mock.Setup(c => c.DeleteActivityAsync(
239 It.IsAny<string>(),
240 It.IsAny<string>(),
241 It.IsAny<Uri>(),
242 It.IsAny<AgenticIdentity>(),
243 It.IsAny<Dictionary<string, string>>(),
244 It.IsAny<CancellationToken>()))
245 .Returns(Task.CompletedTask);
246
247 mock.Setup(c => c.SendActivityAsync(
248 It.IsAny<CoreActivity>(),
249 It.IsAny<Dictionary<string, string>?>(),
250 It.IsAny<CancellationToken>()))
251 .ReturnsAsync(new SendActivityResponse { Id = "default-sent-id" });
252
253 return mock;
254 }
255
256 private static Mock<TeamsBotApplication> CreateMockTeamsBotApplication()
257 {
258 Mock<ConversationClient> mockConversationClient = CreateMockConversationClient();
259 Mock<UserTokenClient> mockUserTokenClient = new(
260 new HttpClient(),
261 Mock.Of<Microsoft.Extensions.Configuration.IConfiguration>(),
262 NullLogger<UserTokenClient>.Instance);
263 ApiClient mockTeamsApiClient = new(
264 new Uri("https://service.url"),
265 new HttpClient(),
266 mockConversationClient.Object,
267 mockUserTokenClient.Object,
268 NullLogger<ApiClient>.Instance);
269
270 Mock<TeamsBotApplication> mock = new(
271 mockConversationClient.Object,
272 mockUserTokenClient.Object,
273 mockTeamsApiClient,
274 Mock.Of<IHttpContextAccessor>(),
275 NullLogger<TeamsBotApplication>.Instance);
276
277 return mock;
278 }
279
280 private static TeamsBotAdapter CreateCompatBotAdapter(ConversationClient conversationClient)
281 {
282 Mock<UserTokenClient> mockUserTokenClient = new(
283 new HttpClient(),
284 Mock.Of<Microsoft.Extensions.Configuration.IConfiguration>(),
285 NullLogger<UserTokenClient>.Instance);
286 ApiClient mockTeamsApiClient = new(
287 new Uri("https://service.url"),
288 new HttpClient(),
289 conversationClient,
290 mockUserTokenClient.Object,
291 NullLogger<ApiClient>.Instance);
292 TeamsBotApplication teamsBotApplication = new(
293 conversationClient,
294 mockUserTokenClient.Object,
295 mockTeamsApiClient,
296 Mock.Of<IHttpContextAccessor>(),
297 NullLogger<TeamsBotApplication>.Instance);
298
299 return new TeamsBotAdapter(
300 teamsBotApplication,
301 Mock.Of<IHttpContextAccessor>(),
302 NullLogger<TeamsBotAdapter>.Instance);
303 }
304
305 private static TeamsBotAdapter CreateCompatBotAdapter(TeamsBotApplication teamsBotApplication)
306 {
307 return new TeamsBotAdapter(
308 teamsBotApplication,
309 Mock.Of<IHttpContextAccessor>(),
310 NullLogger<TeamsBotAdapter>.Instance);
311 }
312
313 private static ITurnContext CreateMockTurnContext(string? serviceUrl)
314 {
315 Activity activity = new()
316 {
317 Type = ActivityTypes.Message,
318 Id = "turn-activity-123",
319 ServiceUrl = serviceUrl,
320 Conversation = new Microsoft.Bot.Schema.ConversationAccount { Id = "turn-conversation-123" },
321 From = new ChannelAccount { Id = "user-123" },
322 Recipient = new ChannelAccount { Id = "bot-123" },
323 ChannelId = "msteams"
324 };
325
326 Mock<ITurnContext> mockTurnContext = new();
327 mockTurnContext.Setup(t => t.Activity).Returns(activity);
328
329 return mockTurnContext.Object;
330 }
331 }
332}
333