microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
docs/update-release-process

Branches

Tags

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

Clone

HTTPS

Download ZIP

Tests/Microsoft.Teams.Api.Tests/Activities/Events/MeetingStartActivityTests.cs

295lines · modecode

1using System.Text.Json;
2
3using Microsoft.Teams.Api.Activities;
4using Microsoft.Teams.Api.Activities.Events;
5
6namespace Microsoft.Teams.Api.Tests.Activities.Events;
7
8public class MeetingStartActivityTests
9{
10 private static readonly JsonSerializerOptions CachedJsonSerializerOptions = new JsonSerializerOptions()
11 {
12 WriteIndented = true,
13 IndentSize = 2,
14 DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
15 };
16
17 public MeetingStartActivity SetupMeetingStartActivity()
18 {
19 return new MeetingStartActivity()
20 {
21 Value = new MeetingStartActivityValue()
22 {
23 Id = "id",
24 MeetingType = "meetingType",
25 JoinUrl = "https://teams.meetingjoin.url/somevalues",
26 Title = "Meeting For Teams.net",
27 StartTime = new DateTime(2025, 1, 1, 4, 30, 00),
28 },
29 Recipient = new Account()
30 {
31 Id = "recipientId",
32 Name = "recipientName"
33 },
34 ChannelId = new ChannelId("msteams"),
35 };
36 }
37
38 [Fact]
39 public void MeetingStartActivity_Props()
40 {
41 var activity = SetupMeetingStartActivity();
42
43 Assert.NotNull(activity.ToMeetingStart());
44 ActivityType expectedEventType = new ActivityType("event");
45 Assert.Equal(expectedEventType.ToString(), activity.Type.Value);
46 Assert.True(activity.Name.IsMeetingStart);
47 Assert.False(activity.IsStreaming);
48 var expectedSubmitException = "Unable to cast object of type 'Microsoft.Teams.Api.Activities.Events.MeetingStartActivity' to type 'Microsoft.Teams.Api.Activities.MessageActivity'.";
49 var ex = Assert.Throws<System.InvalidCastException>(() => activity.ToMessage());
50 Assert.Equal(expectedSubmitException, ex.Message);
51 }
52
53 [Fact]
54 public void MeetingStartActivity_JsonSerialize()
55 {
56 var activity = SetupMeetingStartActivity();
57
58 var json = JsonSerializer.Serialize(activity, CachedJsonSerializerOptions);
59
60 Assert.Equal(File.ReadAllText(
61 @"../../../Json/Activity/Events/MeetingStartActivity.json"
62 ), json);
63 }
64
65
66 [Fact]
67 public void MeetingStartActivity_JsonSerialize_Object()
68 {
69 MeetingStartActivity activity = SetupMeetingStartActivity();
70
71 var json = JsonSerializer.Serialize(activity, CachedJsonSerializerOptions);
72
73 string expectedPath = "Activity.Event.Application/vnd.microsoft.meetingStart";
74 Assert.Equal(expectedPath, activity.GetPath());
75 Assert.Equal(File.ReadAllText(
76 @"../../../Json/Activity/Events/MeetingStartActivity.json"
77 ), json);
78 }
79
80 [Fact]
81 public void MeetingStartActivity_JsonSerialize_Derived_From_Class()
82 {
83 EventActivity activity = SetupMeetingStartActivity();
84
85 var json = JsonSerializer.Serialize(activity, CachedJsonSerializerOptions);
86
87 string expectedPath = "Activity.Event.Application/vnd.microsoft.meetingStart";
88 Assert.Equal(expectedPath, activity.GetPath());
89 Assert.False(activity.Name.IsReadReceipt);
90 Assert.True(activity.Name.IsMeetingStart);
91 Assert.Equal(File.ReadAllText(
92 @"../../../Json/Activity/Events/MeetingStartActivity.json"
93 ), json);
94 }
95
96 [Fact]
97 public void MeetingStartActivity_JsonSerialize_Derived_From_Interface()
98 {
99 IActivity activity = SetupMeetingStartActivity();
100
101 var json = JsonSerializer.Serialize(activity, CachedJsonSerializerOptions);
102
103 string expectedPath = "Activity.Event.Application/vnd.microsoft.meetingStart";
104 Assert.Equal(expectedPath, activity.GetPath());
105 Assert.Equal(File.ReadAllText(
106 @"../../../Json/Activity/Events/MeetingStartActivity.json"
107 ), json);
108 }
109
110 [Fact]
111 public void MeetingStartActivity_JsonDeserialize()
112 {
113 var json = File.ReadAllText(@"../../../Json/Activity/Events/MeetingStartActivity.json");
114 var activity = JsonSerializer.Deserialize<MeetingStartActivity>(json);
115 var expected = SetupMeetingStartActivity();
116
117 Assert.Equal(expected.ToString(), activity!.ToString());
118 Assert.Equal(typeof(MeetingStartActivity), activity.Name.ToType());
119 Assert.Equal("Application/vnd.microsoft.meetingStart", activity.Name.ToPrettyString());
120 Assert.NotNull(activity.ToMeetingStart());
121 }
122
123
124 [Fact]
125 public void MeetingStartActivity_JsonDeserialize_Derived()
126 {
127 var json = File.ReadAllText(@"../../../Json/Activity/Events/MeetingStartActivity.json");
128 var activity = JsonSerializer.Deserialize<EventActivity>(json);
129 var expected = SetupMeetingStartActivity();
130
131 Assert.Equal(expected.ToString(), activity!.ToString());
132 Assert.NotNull(activity.ToEvent());
133 Assert.Equal(typeof(MeetingStartActivity), activity.Name.ToType());
134 var expectedSubmitException = "Unable to cast object of type 'Microsoft.Teams.Api.Activities.Events.MeetingStartActivity' to type 'Microsoft.Teams.Api.Activities.InstallUpdateActivity'.";
135 var ex = Assert.Throws<System.InvalidCastException>(() => activity.ToInstallUpdate());
136 Assert.Equal(expectedSubmitException, ex.Message);
137 }
138
139 [Fact]
140 public void MeetingStartActivity_JsonDeserialize_Activity_Derived()
141 {
142 var json = File.ReadAllText(@"../../../Json/Activity/Events/MeetingStartActivity.json");
143 var activity = JsonSerializer.Deserialize<Activity>(json);
144 var expected = SetupMeetingStartActivity();
145
146 Assert.Equal(expected.ToString(), activity!.ToString());
147 Assert.NotNull(activity.ToEvent());
148 var expectedSubmitException = "Unable to cast object of type 'Microsoft.Teams.Api.Activities.Events.MeetingStartActivity' to type 'Microsoft.Teams.Api.Activities.InstallUpdateActivity'.";
149 var ex = Assert.Throws<System.InvalidCastException>(() => activity.ToInstallUpdate());
150 Assert.Equal(expectedSubmitException, ex.Message);
151 }
152
153 [Fact]
154 public void MeetingStartActivity_JsonDeserialize_TeamsPayload_PascalCase()
155 {
156 // This test verifies that we can deserialize the actual JSON payload sent by Teams
157 // which uses PascalCase for value object properties
158 var json = @"{
159 ""name"": ""application/vnd.microsoft.meetingStart"",
160 ""type"": ""event"",
161 ""timestamp"": ""2025-10-31T10:00:00.0000000Z"",
162 ""id"": ""1761910695514"",
163 ""channelId"": ""msteams"",
164 ""serviceUrl"": ""https://smba.trafficmanager.net/emea/167c22a9-1b2e-439c-ad74-cc77e9e118d8/"",
165 ""from"": {
166 ""id"": ""29:1geTNfcvfJus0De5z4gr7HeHGMOuln9LY8aHFGtwBqhOl7ZYQFcM2CL1ODjhgHE1XTq3vBeeRlGGGPvFWi0BzRw"",
167 ""name"": """",
168 ""aadObjectId"": ""86a23cfc-f78e-424a-8947-7ae0ce242da1""
169 },
170 ""conversation"": {
171 ""isGroup"": true,
172 ""conversationType"": ""groupChat"",
173 ""tenantId"": ""167c22a9-1b2e-439c-ad74-cc77e9e118d8"",
174 ""id"": ""19:meeting_MTRmMTQ5NDYtMTYyYi00NmNlLWI4ZTQtN2I1MTYzM2RkYTg3@thread.v2""
175 },
176 ""recipient"": {
177 ""id"": ""28:c9a052ed-f68c-4227-b081-01da0669c49c"",
178 ""name"": ""teams-bot""
179 },
180 ""value"": {
181 ""MeetingType"": ""Scheduled"",
182 ""Title"": ""Test Meeting"",
183 ""Id"": ""MCMxOTptZWV0aW5nX01UUm1NVFE1TkRZdE1UWXlZaTAwTm1ObExXSTRaVFF0TjJJMU1UWXpNMlJrWVRnM0B0aHJlYWQudjIjMA=="",
184 ""JoinUrl"": ""https://teams.microsoft.com/l/meetup-join/19%3ameeting_MTRmMTQ5NDYtMTYyYi00NmNlLWI4ZTQtN2I1MTYzM2RkYTg3%40thread.v2/0?context=%7b%22Tid%22%3a%22167c22a9-1b2e-439c-ad74-cc77e9e118d8%22%2c%22Oid%22%3a%2286a23cfc-f78e-424a-8947-7ae0ce242da1%22%7d"",
185 ""StartTime"": ""2025-10-31T10:00:00.0000000Z""
186 },
187 ""locale"": ""en-US""
188 }";
189
190 var activity = JsonSerializer.Deserialize<MeetingStartActivity>(json);
191
192 Assert.NotNull(activity);
193 Assert.NotNull(activity.Value);
194 Assert.Equal("MCMxOTptZWV0aW5nX01UUm1NVFE1TkRZdE1UWXlZaTAwTm1ObExXSTRaVFF0TjJJMU1UWXpNMlJrWVRnM0B0aHJlYWQudjIjMA==", activity.Value.Id);
195 Assert.Equal("Scheduled", activity.Value.MeetingType);
196 Assert.Equal("Test Meeting", activity.Value.Title);
197 Assert.Equal("https://teams.microsoft.com/l/meetup-join/19%3ameeting_MTRmMTQ5NDYtMTYyYi00NmNlLWI4ZTQtN2I1MTYzM2RkYTg3%40thread.v2/0?context=%7b%22Tid%22%3a%22167c22a9-1b2e-439c-ad74-cc77e9e118d8%22%2c%22Oid%22%3a%2286a23cfc-f78e-424a-8947-7ae0ce242da1%22%7d", activity.Value.JoinUrl);
198 Assert.Equal(new DateTime(2025, 10, 31, 10, 0, 0, DateTimeKind.Utc), activity.Value.StartTime);
199 }
200
201 [Fact]
202 public void MeetingStartActivity_JsonSerialize_PascalCase_RoundTrip()
203 {
204 // Verify that serialization produces PascalCase and can be deserialized back
205 var activity = new MeetingStartActivity()
206 {
207 Value = new MeetingStartActivityValue()
208 {
209 Id = "startTestId789",
210 MeetingType = "Scheduled",
211 JoinUrl = "https://teams.microsoft.com/l/meetup-join/test",
212 Title = "Morning Standup",
213 StartTime = new DateTime(2025, 12, 10, 9, 0, 0, DateTimeKind.Utc),
214 },
215 Recipient = new Account()
216 {
217 Id = "recipientId",
218 Name = "recipientName"
219 },
220 ChannelId = new ChannelId("msteams"),
221 };
222
223 var json = JsonSerializer.Serialize(activity, CachedJsonSerializerOptions);
224
225 // Verify PascalCase in serialized JSON
226 Assert.Contains("\"Id\":", json);
227 Assert.Contains("\"MeetingType\":", json);
228 Assert.Contains("\"JoinUrl\":", json);
229 Assert.Contains("\"Title\":", json);
230 Assert.Contains("\"StartTime\":", json);
231
232 // Verify round-trip deserialization
233 var deserialized = JsonSerializer.Deserialize<MeetingStartActivity>(json);
234 Assert.NotNull(deserialized);
235 Assert.Equal(activity.Value.Id, deserialized.Value.Id);
236 Assert.Equal(activity.Value.MeetingType, deserialized.Value.MeetingType);
237 Assert.Equal(activity.Value.Title, deserialized.Value.Title);
238 Assert.Equal(activity.Value.JoinUrl, deserialized.Value.JoinUrl);
239 Assert.Equal(activity.Value.StartTime, deserialized.Value.StartTime);
240 }
241
242 [Fact]
243 public void MeetingStartActivity_JsonDeserialize_TeamsPayload_As_EventActivity()
244 {
245 // Verify deserialization works when deserializing as EventActivity base class
246 var json = @"{
247 ""name"": ""application/vnd.microsoft.meetingStart"",
248 ""type"": ""event"",
249 ""channelId"": ""msteams"",
250 ""value"": {
251 ""MeetingType"": ""Adhoc"",
252 ""Title"": ""Impromptu Discussion"",
253 ""Id"": ""adhocId123"",
254 ""JoinUrl"": ""https://teams.microsoft.com/join/adhoc"",
255 ""StartTime"": ""2025-12-10T14:00:00Z""
256 }
257 }";
258
259 var activity = JsonSerializer.Deserialize<EventActivity>(json);
260
261 Assert.NotNull(activity);
262 Assert.True(activity.Name.IsMeetingStart);
263 var meetingStartActivity = activity as MeetingStartActivity;
264 Assert.NotNull(meetingStartActivity);
265 Assert.Equal("adhocId123", meetingStartActivity.Value.Id);
266 Assert.Equal("Adhoc", meetingStartActivity.Value.MeetingType);
267 }
268
269 [Fact]
270 public void MeetingStartActivity_JsonDeserialize_TeamsPayload_As_IActivity()
271 {
272 // Verify deserialization works when deserializing as IActivity interface
273 var json = @"{
274 ""name"": ""application/vnd.microsoft.meetingStart"",
275 ""type"": ""event"",
276 ""channelId"": ""msteams"",
277 ""value"": {
278 ""MeetingType"": ""Recurring"",
279 ""Title"": ""Weekly Sync"",
280 ""Id"": ""recurringId999"",
281 ""JoinUrl"": ""https://teams.microsoft.com/join/recurring/999"",
282 ""StartTime"": ""2025-12-10T11:00:00Z""
283 }
284 }";
285
286 var activity = JsonSerializer.Deserialize<IActivity>(json);
287
288 Assert.NotNull(activity);
289 var meetingStartActivity = activity as MeetingStartActivity;
290 Assert.NotNull(meetingStartActivity);
291 Assert.Equal("recurringId999", meetingStartActivity.Value.Id);
292 Assert.Equal("Recurring", meetingStartActivity.Value.MeetingType);
293 Assert.Equal("Weekly Sync", meetingStartActivity.Value.Title);
294 }
295}