microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
next/core-compat-sso-middleware

Branches

Tags

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

Clone

HTTPS

Download ZIP

core/test/Microsoft.Teams.Bot.Compat.UnitTests/CompatBotAdapterTests.cs

328lines · 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.Bot.Apps;
9using Microsoft.Teams.Bot.Apps.Api.Clients;
10using Microsoft.Teams.Bot.Core;
11using Microsoft.Teams.Bot.Core.Schema;
12using Moq;
13
14namespace Microsoft.Teams.Bot.Compat.UnitTests
15{
16 public class CompatBotAdapterTests
17 {
18 [Fact]
19 public async Task DeleteActivityAsync_UsesConversationReferenceValues()
20 {
21 // Arrange
22 Mock<ConversationClient> mockConversationClient = CreateMockConversationClient();
23 CompatBotAdapter 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 CompatBotAdapter 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 CompatBotAdapter 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 CompatBotAdapter 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 CompatBotAdapter 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 CompatBotAdapter 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<Dictionary<string, string>>(),
196 It.IsAny<CancellationToken>()))
197 .ReturnsAsync(new UpdateActivityResponse { Id = "updated-123" });
198
199 CompatBotAdapter adapter = CreateCompatBotAdapter(mockConversationClient.Object);
200
201 Activity activity = new()
202 {
203 Type = ActivityTypes.Message,
204 Id = "activity-123",
205 Text = "Updated message",
206 Conversation = new Microsoft.Bot.Schema.ConversationAccount { Id = "conversation-123" },
207 ServiceUrl = null // ServiceUrl not set on activity
208 };
209
210 ITurnContext turnContext = CreateMockTurnContext("https://turn-context-service-url.com/");
211
212 // Act
213 ResourceResponse response = await adapter.UpdateActivityAsync(turnContext, activity, CancellationToken.None);
214
215 // Assert
216 Assert.Equal("updated-123", response.Id);
217
218 mockConversationClient.Verify(
219 c => c.UpdateActivityAsync(
220 "conversation-123",
221 "activity-123",
222 It.Is<CoreActivity>(a => a.ServiceUrl != null && a.ServiceUrl.ToString().TrimEnd('/') == "https://turn-context-service-url.com"),
223 null,
224 It.IsAny<CancellationToken>()),
225 Times.Once);
226 }
227
228 private static Mock<ConversationClient> CreateMockConversationClient()
229 {
230 Mock<ConversationClient> mock = new(
231 new HttpClient(),
232 NullLogger<ConversationClient>.Instance);
233
234 mock.Setup(c => c.DeleteActivityAsync(
235 It.IsAny<string>(),
236 It.IsAny<string>(),
237 It.IsAny<Uri>(),
238 It.IsAny<AgenticIdentity>(),
239 It.IsAny<Dictionary<string, string>>(),
240 It.IsAny<CancellationToken>()))
241 .Returns(Task.CompletedTask);
242
243 mock.Setup(c => c.SendActivityAsync(
244 It.IsAny<CoreActivity>(),
245 It.IsAny<Dictionary<string, string>>(),
246 It.IsAny<CancellationToken>()))
247 .ReturnsAsync(new SendActivityResponse { Id = "default-sent-id" });
248
249 return mock;
250 }
251
252 private static Mock<TeamsBotApplication> CreateMockTeamsBotApplication()
253 {
254 Mock<ConversationClient> mockConversationClient = CreateMockConversationClient();
255 Mock<UserTokenClient> mockUserTokenClient = new(
256 new HttpClient(),
257 Mock.Of<Microsoft.Extensions.Configuration.IConfiguration>(),
258 NullLogger<UserTokenClient>.Instance);
259 ApiClient mockTeamsApiClient = new(
260 new Uri("https://service.url"),
261 new HttpClient(),
262 mockConversationClient.Object,
263 mockUserTokenClient.Object,
264 NullLogger<ApiClient>.Instance);
265
266 Mock<TeamsBotApplication> mock = new(
267 mockConversationClient.Object,
268 mockUserTokenClient.Object,
269 mockTeamsApiClient,
270 Mock.Of<IHttpContextAccessor>(),
271 NullLogger<TeamsBotApplication>.Instance);
272
273 return mock;
274 }
275
276 private static CompatBotAdapter CreateCompatBotAdapter(ConversationClient conversationClient)
277 {
278 Mock<UserTokenClient> mockUserTokenClient = new(
279 new HttpClient(),
280 Mock.Of<Microsoft.Extensions.Configuration.IConfiguration>(),
281 NullLogger<UserTokenClient>.Instance);
282 ApiClient mockTeamsApiClient = new(
283 new Uri("https://service.url"),
284 new HttpClient(),
285 conversationClient,
286 mockUserTokenClient.Object,
287 NullLogger<ApiClient>.Instance);
288 TeamsBotApplication teamsBotApplication = new(
289 conversationClient,
290 mockUserTokenClient.Object,
291 mockTeamsApiClient,
292 Mock.Of<IHttpContextAccessor>(),
293 NullLogger<TeamsBotApplication>.Instance);
294
295 return new CompatBotAdapter(
296 teamsBotApplication,
297 Mock.Of<IHttpContextAccessor>(),
298 NullLogger<CompatBotAdapter>.Instance);
299 }
300
301 private static CompatBotAdapter CreateCompatBotAdapter(TeamsBotApplication teamsBotApplication)
302 {
303 return new CompatBotAdapter(
304 teamsBotApplication,
305 Mock.Of<IHttpContextAccessor>(),
306 NullLogger<CompatBotAdapter>.Instance);
307 }
308
309 private static ITurnContext CreateMockTurnContext(string? serviceUrl)
310 {
311 Activity activity = new()
312 {
313 Type = ActivityTypes.Message,
314 Id = "turn-activity-123",
315 ServiceUrl = serviceUrl,
316 Conversation = new Microsoft.Bot.Schema.ConversationAccount { Id = "turn-conversation-123" },
317 From = new ChannelAccount { Id = "user-123" },
318 Recipient = new ChannelAccount { Id = "bot-123" },
319 ChannelId = "msteams"
320 };
321
322 Mock<ITurnContext> mockTurnContext = new();
323 mockTurnContext.Setup(t => t.Activity).Returns(activity);
324
325 return mockTurnContext.Object;
326 }
327 }
328}
329