microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
samples/migration-bot

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

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