microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v2.0.8

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

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