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/CompatActivityTests.cs

432lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Text.Json;
5using System.Text.Json.Nodes;
6using AdaptiveCards;
7using Microsoft.Bot.Schema;
8using Microsoft.Teams.Bot.Core.Schema;
9using Newtonsoft.Json;
10
11namespace Microsoft.Teams.Bot.Compat.UnitTests
12{
13 public class CompatActivityTests
14 {
15 #region Core Properties Tests
16
17 [Fact]
18 public void FromCompatActivity_PreservesCoreProperties()
19 {
20 Activity activity = new()
21 {
22 Type = ActivityTypes.Message,
23 ServiceUrl = "https://smba.trafficmanager.net/teams",
24 ChannelId = "msteams",
25 Id = "test-id-123",
26 From = new ChannelAccount { Id = "user-123", Name = "Test User" },
27 Recipient = new ChannelAccount { Id = "bot-456", Name = "Test Bot" },
28 Conversation = new Microsoft.Bot.Schema.ConversationAccount { Id = "conv-789", Name = "Test Conversation" }
29 };
30
31 CoreActivity coreActivity = activity.FromCompatActivity();
32
33 Assert.NotNull(coreActivity);
34 Assert.Equal(activity.Type, coreActivity.Type);
35 Assert.Equal(activity.ServiceUrl, coreActivity.ServiceUrl?.ToString());
36 Assert.Equal(activity.ChannelId, coreActivity.ChannelId);
37 Assert.Equal(activity.Id, coreActivity.Id);
38 Assert.Equal(activity.From?.Id, coreActivity.From?.Id);
39 Assert.Equal(activity.From?.Name, coreActivity.From?.Name);
40 Assert.Equal(activity.Recipient?.Id, coreActivity.Recipient?.Id);
41 Assert.Equal(activity.Conversation?.Id, coreActivity.Conversation?.Id);
42 }
43
44 [Fact]
45 public void FromCompatActivity_PreservesTextAndMetadata()
46 {
47 Activity activity = new()
48 {
49 Type = ActivityTypes.Message,
50 Text = "Hello, this is a test message",
51 TextFormat = "plain",
52 Locale = "en-US",
53 InputHint = "acceptingInput",
54 ReplyToId = "reply-to-123"
55 };
56
57 CoreActivity coreActivity = activity.FromCompatActivity();
58
59 Assert.NotNull(coreActivity);
60 Assert.Equal(activity.Text, coreActivity.Properties["text"]?.ToString());
61 Assert.Equal(activity.InputHint, coreActivity.Properties["inputHint"]?.ToString());
62 Assert.Equal(activity.ReplyToId, coreActivity.ReplyToId);
63 Assert.Equal(activity.Locale, coreActivity.Properties["locale"]?.ToString());
64 }
65
66 #endregion
67
68 #region Attachments Tests
69
70 [Fact]
71 public void FromCompatActivity_PreservesAdaptiveCardAttachment()
72 {
73 string json = LoadTestData("AdaptiveCardActivity.json");
74 Activity botActivity = JsonConvert.DeserializeObject<Activity>(json)!;
75 Assert.NotNull(botActivity);
76 Assert.Single(botActivity.Attachments);
77
78 CoreActivity coreActivity = botActivity.FromCompatActivity();
79
80 Assert.NotNull(coreActivity);
81 Assert.NotNull(coreActivity.Attachments);
82 Assert.Single(coreActivity.Attachments);
83
84 JsonNode? attachmentNode = coreActivity.Attachments[0];
85 Assert.NotNull(attachmentNode);
86 JsonObject attachmentObj = attachmentNode.AsObject();
87
88 string? contentType = attachmentObj["contentType"]?.GetValue<string>();
89 Assert.Equal("application/vnd.microsoft.card.adaptive", contentType);
90
91 JsonNode? content = attachmentObj["content"];
92 Assert.NotNull(content);
93 AdaptiveCard card = AdaptiveCard.FromJson(content.ToJsonString()).Card;
94 Assert.Equal(2, card.Body?.Count);
95 AdaptiveTextBlock? firstTextBlock = card?.Body?[0] as AdaptiveTextBlock;
96 Assert.NotNull(firstTextBlock);
97 Assert.Equal("Mention a user by User Principle Name: Hello <at>Test User UPN</at>", firstTextBlock.Text);
98 }
99
100 [Fact]
101 public void FromCompatActivity_PreservesMultipleAttachments()
102 {
103 Activity activity = new()
104 {
105 Type = ActivityTypes.Message,
106 Attachments = new List<Attachment>
107 {
108 new() { ContentType = "text/plain", Content = "First attachment" },
109 new() { ContentType = "image/png", ContentUrl = "https://example.com/image.png" }
110 }
111 };
112
113 CoreActivity coreActivity = activity.FromCompatActivity();
114
115 Assert.NotNull(coreActivity.Attachments);
116 Assert.Equal(2, coreActivity.Attachments?.Count);
117 Assert.Equal("text/plain", coreActivity.Attachments?[0]?["contentType"]?.GetValue<string>());
118 Assert.Equal("image/png", coreActivity.Attachments?[1]?["contentType"]?.GetValue<string>());
119 }
120
121 #endregion
122
123 #region Entities Tests
124
125 [Fact]
126 public void FromCompatActivity_PreservesEntities()
127 {
128 string json = LoadTestData("AdaptiveCardActivity.json");
129 Activity botActivity = JsonConvert.DeserializeObject<Activity>(json)!;
130
131 CoreActivity coreActivity = botActivity.FromCompatActivity();
132
133 Assert.NotNull(coreActivity.Entities);
134 Assert.Single(coreActivity.Entities);
135
136 JsonObject? entity = coreActivity.Entities[0]?.AsObject();
137 Assert.NotNull(entity);
138 Assert.Equal("https://schema.org/Message", entity["type"]?.GetValue<string>());
139 }
140
141 [Fact]
142 public void FromCompatActivity_PreservesMultipleEntities()
143 {
144 string json = LoadTestData("SuggestedActionsActivity.json");
145 Activity botActivity = JsonConvert.DeserializeObject<Activity>(json)!;
146
147 CoreActivity coreActivity = botActivity.FromCompatActivity();
148
149 Assert.NotNull(coreActivity.Entities);
150 Assert.Equal(2, coreActivity.Entities?.Count);
151
152 JsonObject? firstEntity = coreActivity.Entities?[0]?.AsObject();
153 Assert.Equal("https://schema.org/Message", firstEntity?["type"]?.GetValue<string>());
154
155 JsonObject? secondEntity = coreActivity.Entities?[1]?.AsObject();
156 Assert.Equal("BotMessageMetadata", secondEntity?["type"]?.GetValue<string>());
157 }
158
159 #endregion
160
161 #region SuggestedActions Tests
162
163 [Fact]
164 public void FromCompatActivity_PreservesSuggestedActions()
165 {
166 string json = LoadTestData("SuggestedActionsActivity.json");
167 Activity botActivity = JsonConvert.DeserializeObject<Activity>(json)!;
168 Assert.NotNull(botActivity.SuggestedActions);
169 Assert.Equal(3, botActivity.SuggestedActions.Actions.Count);
170
171 CoreActivity coreActivity = botActivity.FromCompatActivity();
172
173 Assert.True(coreActivity.Properties.ContainsKey("suggestedActions"));
174
175 string coreActivityJson = coreActivity.ToJson();
176 JsonNode coreActivityNode = JsonNode.Parse(coreActivityJson)!;
177
178 JsonNode? suggestedActions = coreActivityNode["suggestedActions"];
179 Assert.NotNull(suggestedActions);
180
181 JsonArray? actions = suggestedActions["actions"]?.AsArray();
182 Assert.NotNull(actions);
183 Assert.Equal(3, actions.Count);
184 }
185
186 [Fact]
187 public void FromCompatActivity_PreservesSuggestedActionDetails()
188 {
189 string json = LoadTestData("SuggestedActionsActivity.json");
190 Activity botActivity = JsonConvert.DeserializeObject<Activity>(json)!;
191
192 CoreActivity coreActivity = botActivity.FromCompatActivity();
193 string coreActivityJson = coreActivity.ToJson();
194 JsonNode coreActivityNode = JsonNode.Parse(coreActivityJson)!;
195
196 JsonArray? actions = coreActivityNode["suggestedActions"]?["actions"]?.AsArray();
197 Assert.NotNull(actions);
198
199 // Verify Action.Odsl actions
200 Assert.Equal("Action.Odsl", actions[0]?["type"]?.GetValue<string>());
201 Assert.Equal("Add reviewers", actions[0]?["title"]?.GetValue<string>());
202 Assert.NotNull(actions[0]?["value"]);
203
204 Assert.Equal("Action.Odsl", actions[1]?["type"]?.GetValue<string>());
205 Assert.Equal("Open agent settings", actions[1]?["title"]?.GetValue<string>());
206
207 // Verify Action.Compose action
208 Assert.Equal("Action.Compose", actions[2]?["type"]?.GetValue<string>());
209 Assert.Equal("Ask me a question", actions[2]?["title"]?.GetValue<string>());
210 Assert.NotNull(actions[2]?["value"]);
211 }
212
213 #endregion
214
215 #region ChannelData Tests
216
217 [Fact]
218 public void FromCompatActivity_PreservesChannelData()
219 {
220 Activity activity = new()
221 {
222 Type = ActivityTypes.Message,
223 ChannelData = new { customProperty = "customValue", nestedObject = new { key = "value" } }
224 };
225
226 CoreActivity coreActivity = activity.FromCompatActivity();
227
228 Assert.NotNull(coreActivity.ChannelData);
229 Assert.True(coreActivity.ChannelData.Properties.ContainsKey("customProperty"));
230 Assert.Equal("customValue", coreActivity.ChannelData.Properties["customProperty"]?.ToString());
231 }
232
233 [Fact]
234 public void FromCompatActivity_PreservesComplexChannelData()
235 {
236 string json = LoadTestData("SuggestedActionsActivity.json");
237 Activity botActivity = JsonConvert.DeserializeObject<Activity>(json)!;
238
239 CoreActivity coreActivity = botActivity.FromCompatActivity();
240
241 Assert.NotNull(coreActivity.ChannelData);
242 Assert.True(coreActivity.ChannelData.Properties.ContainsKey("feedbackLoopEnabled"));
243
244 JsonElement feedbackLoopValue = (JsonElement)coreActivity.ChannelData.Properties["feedbackLoopEnabled"]!;
245 Assert.True(feedbackLoopValue.GetBoolean());
246 }
247
248 #endregion
249
250 #region Integration Tests
251
252 [Fact]
253 public void FromCompatActivity_CompleteRoundTrip_AdaptiveCard()
254 {
255 // Verify the complete adaptive card payload round-trips successfully
256 string originalJson = LoadTestData("AdaptiveCardActivity.json");
257 Activity botActivity = JsonConvert.DeserializeObject<Activity>(originalJson)!;
258
259 CoreActivity coreActivity = botActivity.FromCompatActivity();
260 string coreActivityJson = coreActivity.ToJson();
261
262 // Use JsonNode.DeepEquals to verify structural equality
263 JsonNode originalNode = JsonNode.Parse(originalJson)!;
264 JsonNode coreNode = JsonNode.Parse(coreActivityJson)!;
265
266 Assert.True(JsonNode.DeepEquals(originalNode, coreNode));
267 }
268
269 [Fact]
270 public void FromCompatActivity_CompleteRoundTrip_SuggestedActions()
271 {
272 // Verify the complete suggested actions payload round-trips successfully
273 string originalJson = LoadTestData("SuggestedActionsActivity.json");
274 Activity botActivity = JsonConvert.DeserializeObject<Activity>(originalJson)!;
275
276 CoreActivity coreActivity = botActivity.FromCompatActivity();
277 string coreActivityJson = coreActivity.ToJson();
278
279 // Use JsonNode.DeepEquals to verify structural equality
280 JsonNode originalNode = JsonNode.Parse(originalJson)!;
281 JsonNode coreNode = JsonNode.Parse(coreActivityJson)!;
282
283 Assert.True(JsonNode.DeepEquals(originalNode, coreNode));
284 }
285
286 #endregion
287
288 private static string LoadTestData(string fileName)
289 {
290 string testDataPath = Path.Combine(AppContext.BaseDirectory, "TestData", fileName);
291 return File.ReadAllText(testDataPath);
292 }
293 }
294
295 public class FromCompatChannelAccountTests
296 {
297 [Fact]
298 public void FromCompatChannelAccount_MapsIdAndName()
299 {
300 Microsoft.Bot.Schema.ChannelAccount account = new() { Id = "user-1", Name = "Alice" };
301
302 Microsoft.Teams.Bot.Core.Schema.ConversationAccount result = account.FromCompatChannelAccount();
303
304 Assert.Equal("user-1", result.Id);
305 Assert.Equal("Alice", result.Name);
306 }
307
308 [Fact]
309 public void FromCompatChannelAccount_MapsAadObjectIdToProperties()
310 {
311 Microsoft.Bot.Schema.ChannelAccount account = new() { Id = "user-1", AadObjectId = "aad-123" };
312
313 Microsoft.Teams.Bot.Core.Schema.ConversationAccount result = account.FromCompatChannelAccount();
314
315 Assert.True(result.Properties.TryGetValue("aadObjectId", out object? val));
316 Assert.Equal("aad-123", val?.ToString());
317 }
318
319 [Fact]
320 public void FromCompatChannelAccount_MapsRoleToUserRoleInProperties()
321 {
322 Microsoft.Bot.Schema.ChannelAccount account = new() { Id = "user-1", Role = "owner" };
323
324 Microsoft.Teams.Bot.Core.Schema.ConversationAccount result = account.FromCompatChannelAccount();
325
326 Assert.True(result.Properties.TryGetValue("userRole", out object? val));
327 Assert.Equal("owner", val?.ToString());
328 }
329
330 [Fact]
331 public void FromCompatChannelAccount_SkipsNullAadObjectIdAndRole()
332 {
333 Microsoft.Bot.Schema.ChannelAccount account = new() { Id = "user-1" };
334
335 Microsoft.Teams.Bot.Core.Schema.ConversationAccount result = account.FromCompatChannelAccount();
336
337 Assert.False(result.Properties.ContainsKey("aadObjectId"));
338 Assert.False(result.Properties.ContainsKey("userRole"));
339 }
340
341 [Fact]
342 public void FromCompatChannelAccount_ThrowsOnNull()
343 {
344 Microsoft.Bot.Schema.ChannelAccount? account = null;
345 Assert.Throws<ArgumentNullException>(() => account!.FromCompatChannelAccount());
346 }
347 }
348
349 public class FromCompatConversationParametersTests
350 {
351 [Fact]
352 public void FromCompatConversationParameters_MapsAllScalarFields()
353 {
354 Microsoft.Bot.Schema.ConversationParameters parameters = new()
355 {
356 IsGroup = true,
357 TopicName = "Test Topic",
358 TenantId = "tenant-abc",
359 ChannelData = new { custom = "data" },
360 };
361
362 Microsoft.Teams.Bot.Core.ConversationParameters result = parameters.FromCompatConversationParameters();
363
364 Assert.True(result.IsGroup);
365 Assert.Equal("Test Topic", result.TopicName);
366 Assert.Equal("tenant-abc", result.TenantId);
367 Assert.NotNull(result.ChannelData);
368 }
369
370 [Fact]
371 public void FromCompatConversationParameters_MapsBotAccount()
372 {
373 Microsoft.Bot.Schema.ConversationParameters parameters = new()
374 {
375 Bot = new Microsoft.Bot.Schema.ChannelAccount { Id = "bot-1", Name = "MyBot" }
376 };
377
378 Microsoft.Teams.Bot.Core.ConversationParameters result = parameters.FromCompatConversationParameters();
379
380 Assert.NotNull(result.Bot);
381 Assert.Equal("bot-1", result.Bot.Id);
382 Assert.Equal("MyBot", result.Bot.Name);
383 }
384
385 [Fact]
386 public void FromCompatConversationParameters_MapsMembers()
387 {
388 Microsoft.Bot.Schema.ConversationParameters parameters = new()
389 {
390 Members =
391 [
392 new Microsoft.Bot.Schema.ChannelAccount { Id = "user-1", Name = "Alice" },
393 new Microsoft.Bot.Schema.ChannelAccount { Id = "user-2", Name = "Bob" },
394 ]
395 };
396
397 Microsoft.Teams.Bot.Core.ConversationParameters result = parameters.FromCompatConversationParameters();
398
399 Assert.NotNull(result.Members);
400 Assert.Equal(2, result.Members.Count);
401 Assert.Equal("user-1", result.Members[0].Id);
402 Assert.Equal("user-2", result.Members[1].Id);
403 }
404
405 [Fact]
406 public void FromCompatConversationParameters_NullActivityProducesNullActivity()
407 {
408 Microsoft.Bot.Schema.ConversationParameters parameters = new() { Activity = null };
409
410 Microsoft.Teams.Bot.Core.ConversationParameters result = parameters.FromCompatConversationParameters();
411
412 Assert.Null(result.Activity);
413 }
414
415 [Fact]
416 public void FromCompatConversationParameters_NullBotProducesNullBot()
417 {
418 Microsoft.Bot.Schema.ConversationParameters parameters = new() { Bot = null };
419
420 Microsoft.Teams.Bot.Core.ConversationParameters result = parameters.FromCompatConversationParameters();
421
422 Assert.Null(result.Bot);
423 }
424
425 [Fact]
426 public void FromCompatConversationParameters_ThrowsOnNull()
427 {
428 Microsoft.Bot.Schema.ConversationParameters? parameters = null;
429 Assert.Throws<ArgumentNullException>(() => parameters!.FromCompatConversationParameters());
430 }
431 }
432}
433