microsoft/teams.net

Public

mirrored from https://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/sub-pr-338

Branches

Tags

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

Clone

HTTPS

Download ZIP

core/test/Microsoft.Teams.Bot.Apps.UnitTests/TeamsActivityTests.cs

364lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Text.Json.Nodes;
5using Microsoft.Teams.Bot.Core.Schema;
6using Microsoft.Teams.Bot.Apps.Schema;
7using Microsoft.Teams.Bot.Apps.Schema.Entities;
8using Microsoft.Teams.Bot.Apps.Schema.MessageActivities;
9
10namespace Microsoft.Teams.Bot.Apps.UnitTests;
11
12public class TeamsActivityTests
13{
14 [Fact]
15 public void DownCastTeamsActivity_To_CoreActivity()
16 {
17 CoreActivity activity = CoreActivity.FromJsonString(json);
18 Assert.Equal("19:6848757105754c8981c67612732d9aa7@thread.tacv2;messageid=1759881511856", activity.Conversation!.Id);
19 TeamsActivity teamsActivity = TeamsActivity.FromActivity(activity);
20 Assert.Equal("19:6848757105754c8981c67612732d9aa7@thread.tacv2;messageid=1759881511856", teamsActivity.Conversation!.Id);
21
22 static void AssertCid(CoreActivity a)
23 {
24 Assert.Equal("19:6848757105754c8981c67612732d9aa7@thread.tacv2;messageid=1759881511856", a.Conversation!.Id);
25 }
26 AssertCid(teamsActivity);
27
28 }
29
30 [Fact]
31 public void DownCastTeamsActivity_To_CoreActivity_FromBuilder()
32 {
33
34 TeamsActivity teamsActivity = TeamsActivity
35 .CreateBuilder()
36 .WithConversation(new Conversation() { Id = "19:6848757105754c8981c67612732d9aa7@thread.tacv2;messageid=1759881511856" })
37 .Build();
38
39 static void AssertCid(CoreActivity a)
40 {
41 Assert.Equal("19:6848757105754c8981c67612732d9aa7@thread.tacv2;messageid=1759881511856", a.Conversation!.Id);
42 }
43 AssertCid(teamsActivity);
44 }
45
46 [Fact]
47 public void DownCastTeamsActivity_To_CoreActivity_WithoutRebase()
48 {
49 TeamsActivity teamsActivity = new TeamsActivity()
50 {
51 Conversation = new TeamsConversation()
52 {
53 Id = "19:6848757105754c8981c67612732d9aa7@thread.tacv2;messageid=1759881511856"
54 }
55 };
56 Assert.Equal("19:6848757105754c8981c67612732d9aa7@thread.tacv2;messageid=1759881511856", teamsActivity.Conversation!.Id);
57
58 static void AssertCid(CoreActivity a)
59 {
60 Assert.Equal("19:6848757105754c8981c67612732d9aa7@thread.tacv2;messageid=1759881511856", a.Conversation!.Id);
61 }
62 AssertCid(teamsActivity);
63
64 }
65
66
67 [Fact]
68 public void AddMentionEntity_To_TeamsActivity()
69 {
70 TeamsActivity activity = TeamsActivity.FromActivity(new CoreActivity(ActivityType.Message));
71 activity
72 .AddMention(new ConversationAccount
73 {
74 Id = "user-id-01",
75 Name = "rido"
76 }, "ridotest");
77
78
79
80 Assert.NotNull(activity.Entities);
81 Assert.Single(activity.Entities);
82 Assert.Equal("mention", activity.Entities[0].Type);
83 MentionEntity? mention = activity.Entities[0] as MentionEntity;
84 Assert.NotNull(mention);
85 Assert.Equal("user-id-01", mention.Mentioned?.Id);
86 Assert.Equal("rido", mention.Mentioned?.Name);
87 Assert.Equal("<at>ridotest</at>", mention.Text);
88
89 string jsonResult = activity.ToJson();
90 Assert.Contains("user-id-01", jsonResult);
91 }
92
93 [Fact]
94 public void AddMentionEntity_Serialize_From_CoreActivity()
95 {
96 TeamsActivity activity = TeamsActivity.FromActivity(new CoreActivity(ActivityType.Message));
97 activity.AddMention(new ConversationAccount
98 {
99 Id = "user-id-01",
100 Name = "rido"
101 }, "ridotest");
102
103
104
105 Assert.NotNull(activity.Entities);
106 Assert.Single(activity.Entities);
107 Assert.Equal("mention", activity.Entities[0].Type);
108 MentionEntity? mention = activity.Entities[0] as MentionEntity;
109 Assert.NotNull(mention);
110 Assert.Equal("user-id-01", mention.Mentioned?.Id);
111 Assert.Equal("rido", mention.Mentioned?.Name);
112 Assert.Equal("<at>ridotest</at>", mention.Text);
113
114 static void SerializeAndAssert(CoreActivity a)
115 {
116 string json = a.ToJson();
117 Assert.Contains("user-id-01", json);
118 }
119
120 SerializeAndAssert(activity);
121 }
122
123
124 [Fact]
125 public void TeamsActivityBuilder_FluentAPI()
126 {
127 TeamsActivity activity = TeamsActivity.CreateBuilder()
128 .WithType(TeamsActivityType.Message)
129 .WithText("Hello World")
130 .WithChannelId("msteams")
131 .AddMention(new ConversationAccount
132 {
133 Id = "user-123",
134 Name = "TestUser"
135 })
136 .Build();
137
138 Assert.Equal(ActivityType.Message, activity.Type);
139 Assert.Equal("<at>TestUser</at> Hello World", activity.Properties["text"]);
140 Assert.Equal("msteams", activity.ChannelId);
141 Assert.NotNull(activity.Entities);
142 Assert.Single(activity.Entities);
143
144 MentionEntity? mention = activity.Entities[0] as MentionEntity;
145 Assert.NotNull(mention);
146 Assert.Equal("user-123", mention.Mentioned?.Id);
147 Assert.Equal("TestUser", mention.Mentioned?.Name);
148 }
149
150 [Fact]
151 public void Serialize_TeamsActivity_WithEntities()
152 {
153 TeamsActivity activity = TeamsActivity.CreateBuilder()
154 .WithType(ActivityType.Message)
155 .WithText("Hello World")
156 .WithChannelId("msteams")
157 .Build();
158
159 activity.AddClientInfo("Web", "US", "America/Los_Angeles", "en-US");
160
161 string jsonResult = activity.ToJson();
162 Assert.Contains("clientInfo", jsonResult);
163 Assert.Contains("Web", jsonResult);
164 Assert.Contains("Hello World", jsonResult);
165 }
166
167 [Fact]
168 public void Deserialize_TeamsActivity_Invoke_WithValue()
169 {
170 //TeamsActivity activity = CoreActivity.FromJsonString<TeamsActivity>(jsonInvoke);
171 TeamsActivity activity = TeamsActivity.FromActivity(CoreActivity.FromJsonString(jsonInvoke));
172 Assert.NotNull(activity.Value);
173 string feedback = activity.Value?["action"]?["data"]?["feedback"]?.ToString()!;
174 Assert.Equal("test invokes", feedback);
175 }
176
177 [Fact]
178 public void Serialize_Does_Not_Repeat_AAdObjectId()
179 {
180 var coreActivity = CoreActivity.FromJsonString("""
181 {
182 "type": "message",
183 "recipient": {
184 "id": "rec1",
185 "name": "recname",
186 "aadObjectId": "rec-aadId-1"
187 }
188 }
189 """);
190 var teamsActivity = TeamsActivity.FromActivity(coreActivity);
191 string json = teamsActivity.ToJson();
192 string[] found = json.Split("aadObjectId");
193 Assert.Equal(1, found.Length - 1); // only one occurrence
194 }
195
196 [Fact]
197 public void FromActivity_Overrides_Recipient()
198 {
199 var coreActivity = CoreActivity.FromJsonString("""
200 {
201 "type": "message",
202 "recipient": {
203 "id": "rec1",
204 "name": "recname",
205 "agenticUserId": "0d5eb8a3-1642-4e63-9ccc-a89aa461716c",
206 "agenticAppId": "3fc62d4f-b04e-4c71-878b-02a2fa395fe2",
207 "agenticAppBlueprintId": "24fff850-d7fb-4d32-a6e7-a1178874430e"
208 }
209 }
210 """);
211 var teamsActivity = TeamsActivity.FromActivity(coreActivity);
212 Assert.Equal("rec1", teamsActivity.Recipient?.Id);
213 Assert.Equal("recname", teamsActivity.Recipient?.Name);
214 var agenticIdentity = AgenticIdentity.FromProperties(teamsActivity.Recipient?.Properties);
215 Assert.NotNull(agenticIdentity);
216 Assert.Equal("0d5eb8a3-1642-4e63-9ccc-a89aa461716c", agenticIdentity.AgenticUserId);
217 Assert.Equal("3fc62d4f-b04e-4c71-878b-02a2fa395fe2", agenticIdentity.AgenticAppId);
218 Assert.Equal("24fff850-d7fb-4d32-a6e7-a1178874430e", agenticIdentity.AgenticAppBlueprintId);
219 }
220
221 private const string jsonInvoke = """
222 {
223 "type": "invoke",
224 "channelId": "msteams",
225 "id": "f:17b96347-e8b4-f340-10bc-eb52fc1a6ad4",
226 "serviceUrl": "https://smba.trafficmanager.net/amer/56653e9d-2158-46ee-90d7-675c39642038/",
227 "channelData": {
228 "tenant": {
229 "id": "56653e9d-2158-46ee-90d7-675c39642038"
230 },
231 "source": {
232 "name": "message"
233 },
234 "legacy": {
235 "replyToId": "1:12SWreU4430kJA9eZCb1kXDuo6A8KdDEGB6d9TkjuDYM"
236 }
237 },
238 "from": {
239 "id": "29:1uMVvhoAyfTqdMsyvHL0qlJTTfQF9MOUSI8_cQts2kdSWEZVDyJO2jz-CsNOhQcdYq1Bw4cHT0__O6XDj4AZ-Jw",
240 "name": "Rido",
241 "aadObjectId": "c5e99701-2a32-49c1-a660-4629ceeb8c61"
242 },
243 "recipient": {
244 "id": "28:aabdbd62-bc97-4afb-83ee-575594577de5",
245 "name": "ridobotlocal"
246 },
247 "conversation": {
248 "id": "a:17vxw6pGQOb3Zfh8acXT8m_PqHycYpaFgzu2mFMUfkT-h0UskMctq5ZPPc7FIQxn2bx7rBSm5yE_HeUXsCcKZBrv77RgorB3_1_pAdvMhi39ClxQgawzyQ9GBFkdiwOxT",
249 "conversationType": "personal",
250 "tenantId": "56653e9d-2158-46ee-90d7-675c39642038"
251 },
252 "entities": [
253 {
254 "locale": "en-US",
255 "country": "US",
256 "platform": "Web",
257 "timezone": "America/Los_Angeles",
258 "type": "clientInfo"
259 }
260 ],
261 "value": {
262 "action": {
263 "type": "Action.Execute",
264 "title": "Submit Feedback",
265 "data": {
266 "feedback": "test invokes"
267 }
268 },
269 "trigger": "manual"
270 },
271 "name": "adaptiveCard/action",
272 "timestamp": "2026-01-07T06:04:59.89Z",
273 "localTimestamp": "2026-01-06T22:04:59.89-08:00",
274 "replyToId": "1767765488332",
275 "locale": "en-US",
276 "localTimezone": "America/Los_Angeles"
277 }
278 """;
279
280 private const string json = """
281 {
282 "type": "message",
283 "channelId": "msteams",
284 "text": "\u003Cat\u003Eridotest\u003C/at\u003E reply to thread",
285 "id": "1759944781430",
286 "serviceUrl": "https://smba.trafficmanager.net/amer/50612dbb-0237-4969-b378-8d42590f9c00/",
287 "channelData": {
288 "teamsChannelId": "19:6848757105754c8981c67612732d9aa7@thread.tacv2",
289 "teamsTeamId": "19:66P469zibfbsGI-_a0aN_toLTZpyzS6u7CT3TsXdgPw1@thread.tacv2",
290 "channel": {
291 "id": "19:6848757105754c8981c67612732d9aa7@thread.tacv2"
292 },
293 "team": {
294 "id": "19:66P469zibfbsGI-_a0aN_toLTZpyzS6u7CT3TsXdgPw1@thread.tacv2"
295 },
296 "tenant": {
297 "id": "50612dbb-0237-4969-b378-8d42590f9c00"
298 }
299 },
300 "from": {
301 "id": "29:17bUvCasIPKfQIXHvNzcPjD86fwm6GkWc1PvCGP2-NSkNb7AyGYpjQ7Xw-XgTwaHW5JxZ4KMNDxn1kcL8fwX1Nw",
302 "name": "rido",
303 "aadObjectId": "b15a9416-0ad3-4172-9210-7beb711d3f70"
304 },
305 "recipient": {
306 "id": "28:0b6fe6d1-fece-44f7-9a48-56465e2d5ab8",
307 "name": "ridotest"
308 },
309 "conversation": {
310 "id": "19:6848757105754c8981c67612732d9aa7@thread.tacv2;messageid=1759881511856",
311 "isGroup": true,
312 "conversationType": "channel",
313 "tenantId": "50612dbb-0237-4969-b378-8d42590f9c00"
314 },
315 "entities": [
316 {
317 "mentioned": {
318 "id": "28:0b6fe6d1-fece-44f7-9a48-56465e2d5ab8",
319 "name": "ridotest"
320 },
321 "text": "\u003Cat\u003Eridotest\u003C/at\u003E",
322 "type": "mention"
323 },
324 {
325 "locale": "en-US",
326 "country": "US",
327 "platform": "Web",
328 "timezone": "America/Los_Angeles",
329 "type": "clientInfo"
330 }
331 ],
332 "textFormat": "plain",
333 "attachments": [
334 {
335 "contentType": "text/html",
336 "content": "\u003Cp\u003E\u003Cspan itemtype=\u0022http://schema.skype.com/Mention\u0022 itemscope=\u0022\u0022 itemid=\u00220\u0022\u003Eridotest\u003C/span\u003E\u0026nbsp;reply to thread\u003C/p\u003E"
337 }
338 ],
339 "timestamp": "2025-10-08T17:33:01.4953744Z",
340 "localTimestamp": "2025-10-08T10:33:01.4953744-07:00",
341 "locale": "en-US",
342 "localTimezone": "America/Los_Angeles"
343 }
344 """;
345
346 [Fact]
347 public void FromActivity_ReturnsDerivedType_WhenRegistered()
348 {
349 CoreActivity coreActivity = new CoreActivity(ActivityType.Message);
350 TeamsActivity activity = TeamsActivity.FromActivity(coreActivity);
351
352 Assert.IsType<MessageActivity>(activity);
353 }
354
355 [Fact]
356 public void FromActivity_ReturnsBaseType_WhenNotRegistered()
357 {
358 CoreActivity coreActivity = new CoreActivity("unknownType");
359 TeamsActivity activity = TeamsActivity.FromActivity(coreActivity);
360
361 Assert.Equal(typeof(TeamsActivity), activity.GetType());
362 Assert.Equal("unknownType", activity.Type);
363 }
364}
365