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.Core.Tests/TeamsApiClientTests.cs

562lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using Microsoft.Teams.Bot.Core;
5using Microsoft.Teams.Bot.Core.Hosting;
6using Microsoft.Teams.Bot.Core.Schema;
7using Microsoft.Extensions.Configuration;
8using Microsoft.Extensions.DependencyInjection;
9using Microsoft.Teams.Bot.Apps;
10
11namespace Microsoft.Bot.Core.Tests;
12
13public class TeamsApiClientTests
14{
15 private readonly ServiceProvider _serviceProvider;
16 private readonly TeamsApiClient _teamsClient;
17 private readonly Uri _serviceUrl;
18
19 public TeamsApiClientTests()
20 {
21 IConfigurationBuilder builder = new ConfigurationBuilder()
22 .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
23 .AddEnvironmentVariables();
24
25 IConfiguration configuration = builder.Build();
26
27 ServiceCollection services = new();
28 services.AddLogging();
29 services.AddSingleton(configuration);
30 services.AddTeamsBotApplication();
31 _serviceProvider = services.BuildServiceProvider();
32 _teamsClient = _serviceProvider.GetRequiredService<TeamsApiClient>();
33 _serviceUrl = new Uri(Environment.GetEnvironmentVariable("TEST_SERVICEURL") ?? "https://smba.trafficmanager.net/teams/");
34 }
35
36 #region Team Operations Tests
37
38 [Fact]
39 public async Task FetchChannelList()
40 {
41 string teamId = Environment.GetEnvironmentVariable("TEST_TEAMID") ?? throw new InvalidOperationException("TEST_TEAMID environment variable not set");
42
43 ChannelList result = await _teamsClient.FetchChannelListAsync(
44 teamId,
45 _serviceUrl,
46 cancellationToken: CancellationToken.None);
47
48 Assert.NotNull(result);
49 Assert.NotNull(result.Channels);
50 Assert.NotEmpty(result.Channels);
51
52 Console.WriteLine($"Found {result.Channels.Count} channels in team {teamId}:");
53 foreach (var channel in result.Channels)
54 {
55 Console.WriteLine($" - Id: {channel.Id}, Name: {channel.Name}");
56 Assert.NotNull(channel);
57 Assert.NotNull(channel.Id);
58 }
59 }
60
61 [Fact]
62 public async Task FetchChannelList_FailsWithInvalidTeamId()
63 {
64 await Assert.ThrowsAsync<HttpRequestException>(()
65 => _teamsClient.FetchChannelListAsync("invalid-team-id", _serviceUrl));
66 }
67
68 [Fact]
69 public async Task FetchTeamDetails()
70 {
71 string teamId = Environment.GetEnvironmentVariable("TEST_TEAMID") ?? throw new InvalidOperationException("TEST_TEAMID environment variable not set");
72
73 TeamDetails result = await _teamsClient.FetchTeamDetailsAsync(
74 teamId,
75 _serviceUrl,
76 cancellationToken: CancellationToken.None);
77
78 Assert.NotNull(result);
79 Assert.NotNull(result.Id);
80
81 Console.WriteLine($"Team details for {teamId}:");
82 Console.WriteLine($" - Id: {result.Id}");
83 Console.WriteLine($" - Name: {result.Name}");
84 Console.WriteLine($" - AAD Group Id: {result.AadGroupId}");
85 Console.WriteLine($" - Channel Count: {result.ChannelCount}");
86 Console.WriteLine($" - Member Count: {result.MemberCount}");
87 Console.WriteLine($" - Type: {result.Type}");
88 }
89
90 [Fact]
91 public async Task FetchTeamDetails_FailsWithInvalidTeamId()
92 {
93 await Assert.ThrowsAsync<HttpRequestException>(()
94 => _teamsClient.FetchTeamDetailsAsync("invalid-team-id", _serviceUrl));
95 }
96
97 #endregion
98
99 #region Meeting Operations Tests
100
101 [Fact]
102 public async Task FetchMeetingInfo()
103 {
104 string meetingId = Environment.GetEnvironmentVariable("TEST_MEETINGID") ?? throw new InvalidOperationException("TEST_MEETINGID environment variable not set");
105
106 MeetingInfo result = await _teamsClient.FetchMeetingInfoAsync(
107 meetingId,
108 _serviceUrl,
109 cancellationToken: CancellationToken.None);
110
111 Assert.NotNull(result);
112 //Assert.NotNull(result.Id);
113
114 Console.WriteLine($"Meeting info for {meetingId}:");
115
116 if (result.Details != null)
117 {
118 Console.WriteLine($" - Title: {result.Details.Title}");
119 Console.WriteLine($" - Type: {result.Details.Type}");
120 Console.WriteLine($" - Join URL: {result.Details.JoinUrl}");
121 Console.WriteLine($" - Scheduled Start: {result.Details.ScheduledStartTime}");
122 Console.WriteLine($" - Scheduled End: {result.Details.ScheduledEndTime}");
123 }
124 if (result.Organizer != null)
125 {
126 Console.WriteLine($" - Organizer: {result.Organizer.Name} ({result.Organizer.Id})");
127 }
128 }
129
130 [Fact]
131 public async Task FetchMeetingInfo_FailsWithInvalidMeetingId()
132 {
133 await Assert.ThrowsAsync<HttpRequestException>(()
134 => _teamsClient.FetchMeetingInfoAsync("invalid-meeting-id", _serviceUrl));
135 }
136
137 [Fact]
138 public async Task FetchParticipant()
139 {
140 string meetingId = Environment.GetEnvironmentVariable("TEST_MEETINGID") ?? throw new InvalidOperationException("TEST_MEETINGID environment variable not set");
141 string participantId = Environment.GetEnvironmentVariable("TEST_USER_ID") ?? throw new InvalidOperationException("TEST_USER_ID environment variable not set");
142 string tenantId = Environment.GetEnvironmentVariable("TEST_TENANTID") ?? throw new InvalidOperationException("TEST_TENANTID environment variable not set");
143
144 MeetingParticipant result = await _teamsClient.FetchParticipantAsync(
145 meetingId,
146 participantId,
147 tenantId,
148 _serviceUrl,
149 cancellationToken: CancellationToken.None);
150
151 Assert.NotNull(result);
152
153 Console.WriteLine($"Participant info for {participantId} in meeting {meetingId}:");
154 if (result.User != null)
155 {
156 Console.WriteLine($" - User Id: {result.User.Id}");
157 Console.WriteLine($" - User Name: {result.User.Name}");
158 }
159 if (result.Meeting != null)
160 {
161 Console.WriteLine($" - Role: {result.Meeting.Role}");
162 Console.WriteLine($" - In Meeting: {result.Meeting.InMeeting}");
163 }
164 }
165
166 [Fact(Skip = "Requires active meeting context")]
167 public async Task SendMeetingNotification()
168 {
169 string meetingId = Environment.GetEnvironmentVariable("TEST_MEETINGID") ?? throw new InvalidOperationException("TEST_MEETINGID environment variable not set");
170 string participantId = Environment.GetEnvironmentVariable("TEST_USER_ID") ?? throw new InvalidOperationException("TEST_USER_ID environment variable not set");
171
172 var notification = new TargetedMeetingNotification
173 {
174 Value = new TargetedMeetingNotificationValue
175 {
176 Recipients = [participantId],
177 Surfaces =
178 [
179 new MeetingNotificationSurface
180 {
181 Surface = "meetingStage",
182 ContentType = "task",
183 Content = new { title = "Test Notification", url = "https://example.com" }
184 }
185 ]
186 }
187 };
188
189 MeetingNotificationResponse result = await _teamsClient.SendMeetingNotificationAsync(
190 meetingId,
191 notification,
192 _serviceUrl,
193 cancellationToken: CancellationToken.None);
194
195 Assert.NotNull(result);
196
197 Console.WriteLine($"Meeting notification sent to meeting {meetingId}");
198 if (result.RecipientsFailureInfo != null && result.RecipientsFailureInfo.Count > 0)
199 {
200 Console.WriteLine($"Failed recipients:");
201 foreach (var failure in result.RecipientsFailureInfo)
202 {
203 Console.WriteLine($" - {failure.RecipientMri}: {failure.ErrorCode} - {failure.FailureReason}");
204 }
205 }
206 }
207
208 #endregion
209
210 #region Batch Message Operations Tests
211
212 [Fact(Skip = "Batch operations require special permissions")]
213 public async Task SendMessageToListOfUsers()
214 {
215 string tenantId = Environment.GetEnvironmentVariable("TENANT_ID") ?? throw new InvalidOperationException("TENANT_ID environment variable not set");
216 string userId = Environment.GetEnvironmentVariable("TEST_USER_ID") ?? throw new InvalidOperationException("TEST_USER_ID environment variable not set");
217
218 CoreActivity activity = new()
219 {
220 Type = ActivityType.Message,
221 Properties = { { "text", $"Batch message from Automated tests at `{DateTime.UtcNow:s}`" } }
222 };
223
224 IList<TeamMember> members =
225 [
226 new TeamMember(userId)
227 ];
228
229 string operationId = await _teamsClient.SendMessageToListOfUsersAsync(
230 activity,
231 members,
232 tenantId,
233 _serviceUrl,
234 cancellationToken: CancellationToken.None);
235
236 Assert.NotNull(operationId);
237 Assert.NotEmpty(operationId);
238
239 Console.WriteLine($"Batch message sent. Operation ID: {operationId}");
240 }
241
242 [Fact(Skip = "Batch operations require special permissions")]
243 public async Task SendMessageToAllUsersInTenant()
244 {
245 string tenantId = Environment.GetEnvironmentVariable("TENANT_ID") ?? throw new InvalidOperationException("TENANT_ID environment variable not set");
246
247 CoreActivity activity = new()
248 {
249 Type = ActivityType.Message,
250 Properties = { { "text", $"Tenant-wide message from Automated tests at `{DateTime.UtcNow:s}`" } }
251 };
252
253 string operationId = await _teamsClient.SendMessageToAllUsersInTenantAsync(
254 activity,
255 tenantId,
256 _serviceUrl,
257 cancellationToken: CancellationToken.None);
258
259 Assert.NotNull(operationId);
260 Assert.NotEmpty(operationId);
261
262 Console.WriteLine($"Tenant-wide message sent. Operation ID: {operationId}");
263 }
264
265 [Fact(Skip = "Batch operations require special permissions")]
266 public async Task SendMessageToAllUsersInTeam()
267 {
268 string tenantId = Environment.GetEnvironmentVariable("TENANT_ID") ?? throw new InvalidOperationException("TENANT_ID environment variable not set");
269 string teamId = Environment.GetEnvironmentVariable("TEST_TEAMID") ?? throw new InvalidOperationException("TEST_TEAMID environment variable not set");
270
271 CoreActivity activity = new()
272 {
273 Type = ActivityType.Message,
274 Properties = { { "text", $"Team-wide message from Automated tests at `{DateTime.UtcNow:s}`" } }
275 };
276
277 string operationId = await _teamsClient.SendMessageToAllUsersInTeamAsync(
278 activity,
279 teamId,
280 tenantId,
281 _serviceUrl,
282 cancellationToken: CancellationToken.None);
283
284 Assert.NotNull(operationId);
285 Assert.NotEmpty(operationId);
286
287 Console.WriteLine($"Team-wide message sent. Operation ID: {operationId}");
288 }
289
290 [Fact(Skip = "Batch operations require special permissions")]
291 public async Task SendMessageToListOfChannels()
292 {
293 string tenantId = Environment.GetEnvironmentVariable("TENANT_ID") ?? throw new InvalidOperationException("TENANT_ID environment variable not set");
294 string channelId = Environment.GetEnvironmentVariable("TEST_CHANNELID") ?? throw new InvalidOperationException("TEST_CHANNELID environment variable not set");
295
296 CoreActivity activity = new()
297 {
298 Type = ActivityType.Message,
299 Properties = { { "text", $"Channel batch message from Automated tests at `{DateTime.UtcNow:s}`" } }
300 };
301
302 IList<TeamMember> channels =
303 [
304 new TeamMember(channelId)
305 ];
306
307 string operationId = await _teamsClient.SendMessageToListOfChannelsAsync(
308 activity,
309 channels,
310 tenantId,
311 _serviceUrl,
312 cancellationToken: CancellationToken.None);
313
314 Assert.NotNull(operationId);
315 Assert.NotEmpty(operationId);
316
317 Console.WriteLine($"Channel batch message sent. Operation ID: {operationId}");
318 }
319
320 #endregion
321
322 #region Batch Operation Management Tests
323
324 [Fact(Skip = "Requires valid operation ID from batch operation")]
325 public async Task GetOperationState()
326 {
327 string operationId = Environment.GetEnvironmentVariable("TEST_OPERATION_ID") ?? throw new InvalidOperationException("TEST_OPERATION_ID environment variable not set");
328
329 BatchOperationState result = await _teamsClient.GetOperationStateAsync(
330 operationId,
331 _serviceUrl,
332 cancellationToken: CancellationToken.None);
333
334 Assert.NotNull(result);
335 Assert.NotNull(result.State);
336
337 Console.WriteLine($"Operation state for {operationId}:");
338 Console.WriteLine($" - State: {result.State}");
339 Console.WriteLine($" - Total Entries: {result.TotalEntriesCount}");
340 if (result.StatusMap != null)
341 {
342 Console.WriteLine($" - Success: {result.StatusMap.Success}");
343 Console.WriteLine($" - Failed: {result.StatusMap.Failed}");
344 Console.WriteLine($" - Throttled: {result.StatusMap.Throttled}");
345 Console.WriteLine($" - Pending: {result.StatusMap.Pending}");
346 }
347 if (result.RetryAfter != null)
348 {
349 Console.WriteLine($" - Retry After: {result.RetryAfter}");
350 }
351 }
352
353 [Fact]
354 public async Task GetOperationState_FailsWithInvalidOperationId()
355 {
356 await Assert.ThrowsAsync<HttpRequestException>(()
357 => _teamsClient.GetOperationStateAsync("invalid-operation-id", _serviceUrl));
358 }
359
360 [Fact(Skip = "Requires valid operation ID from batch operation")]
361 public async Task GetPagedFailedEntries()
362 {
363 string operationId = Environment.GetEnvironmentVariable("TEST_OPERATION_ID") ?? throw new InvalidOperationException("TEST_OPERATION_ID environment variable not set");
364
365 BatchFailedEntriesResponse result = await _teamsClient.GetPagedFailedEntriesAsync(
366 operationId,
367 _serviceUrl,
368 cancellationToken: CancellationToken.None);
369
370 Assert.NotNull(result);
371
372 Console.WriteLine($"Failed entries for operation {operationId}:");
373 if (result.FailedEntries != null && result.FailedEntries.Count > 0)
374 {
375 foreach (var entry in result.FailedEntries)
376 {
377 Console.WriteLine($" - Id: {entry.Id}, Error: {entry.Error}");
378 }
379 }
380 else
381 {
382 Console.WriteLine(" No failed entries");
383 }
384
385 if (!string.IsNullOrWhiteSpace(result.ContinuationToken))
386 {
387 Console.WriteLine($"Continuation token: {result.ContinuationToken}");
388 }
389 }
390
391 [Fact(Skip = "Requires valid operation ID from batch operation")]
392 public async Task CancelOperation()
393 {
394 string operationId = Environment.GetEnvironmentVariable("TEST_OPERATION_ID") ?? throw new InvalidOperationException("TEST_OPERATION_ID environment variable not set");
395
396 await _teamsClient.CancelOperationAsync(
397 operationId,
398 _serviceUrl,
399 cancellationToken: CancellationToken.None);
400
401 Console.WriteLine($"Operation {operationId} cancelled successfully");
402 }
403
404 #endregion
405
406 #region Argument Validation Tests
407
408 [Fact]
409 public async Task FetchChannelList_ThrowsOnNullTeamId()
410 {
411 await Assert.ThrowsAsync<ArgumentNullException>(()
412 => _teamsClient.FetchChannelListAsync(null!, _serviceUrl));
413 }
414
415 [Fact]
416 public async Task FetchChannelList_ThrowsOnEmptyTeamId()
417 {
418 await Assert.ThrowsAsync<ArgumentException>(()
419 => _teamsClient.FetchChannelListAsync("", _serviceUrl));
420 }
421
422 [Fact]
423 public async Task FetchChannelList_ThrowsOnNullServiceUrl()
424 {
425 await Assert.ThrowsAsync<ArgumentNullException>(()
426 => _teamsClient.FetchChannelListAsync("team-id", null!));
427 }
428
429 [Fact]
430 public async Task FetchTeamDetails_ThrowsOnNullTeamId()
431 {
432 await Assert.ThrowsAsync<ArgumentNullException>(()
433 => _teamsClient.FetchTeamDetailsAsync(null!, _serviceUrl));
434 }
435
436 [Fact]
437 public async Task FetchMeetingInfo_ThrowsOnNullMeetingId()
438 {
439 await Assert.ThrowsAsync<ArgumentNullException>(()
440 => _teamsClient.FetchMeetingInfoAsync(null!, _serviceUrl));
441 }
442
443 [Fact]
444 public async Task FetchParticipant_ThrowsOnNullMeetingId()
445 {
446 await Assert.ThrowsAsync<ArgumentNullException>(()
447 => _teamsClient.FetchParticipantAsync(null!, "participant", "tenant", _serviceUrl));
448 }
449
450 [Fact]
451 public async Task FetchParticipant_ThrowsOnNullParticipantId()
452 {
453 await Assert.ThrowsAsync<ArgumentNullException>(()
454 => _teamsClient.FetchParticipantAsync("meeting", null!, "tenant", _serviceUrl));
455 }
456
457 [Fact]
458 public async Task FetchParticipant_ThrowsOnNullTenantId()
459 {
460 await Assert.ThrowsAsync<ArgumentNullException>(()
461 => _teamsClient.FetchParticipantAsync("meeting", "participant", null!, _serviceUrl));
462 }
463
464 [Fact]
465 public async Task SendMeetingNotification_ThrowsOnNullMeetingId()
466 {
467 var notification = new TargetedMeetingNotification();
468 await Assert.ThrowsAsync<ArgumentNullException>(()
469 => _teamsClient.SendMeetingNotificationAsync(null!, notification, _serviceUrl));
470 }
471
472 [Fact]
473 public async Task SendMeetingNotification_ThrowsOnNullNotification()
474 {
475 await Assert.ThrowsAsync<ArgumentNullException>(()
476 => _teamsClient.SendMeetingNotificationAsync("meeting", null!, _serviceUrl));
477 }
478
479 [Fact]
480 public async Task SendMessageToListOfUsers_ThrowsOnNullActivity()
481 {
482 await Assert.ThrowsAsync<ArgumentNullException>(()
483 => _teamsClient.SendMessageToListOfUsersAsync(null!, [new TeamMember("id")], "tenant", _serviceUrl));
484 }
485
486 [Fact]
487 public async Task SendMessageToListOfUsers_ThrowsOnNullMembers()
488 {
489 var activity = new CoreActivity { Type = ActivityType.Message };
490 await Assert.ThrowsAsync<ArgumentNullException>(()
491 => _teamsClient.SendMessageToListOfUsersAsync(activity, null!, "tenant", _serviceUrl));
492 }
493
494 [Fact]
495 public async Task SendMessageToListOfUsers_ThrowsOnEmptyMembers()
496 {
497 var activity = new CoreActivity { Type = ActivityType.Message };
498 await Assert.ThrowsAsync<ArgumentException>(()
499 => _teamsClient.SendMessageToListOfUsersAsync(activity, [], "tenant", _serviceUrl));
500 }
501
502 [Fact]
503 public async Task SendMessageToAllUsersInTenant_ThrowsOnNullActivity()
504 {
505 await Assert.ThrowsAsync<ArgumentNullException>(()
506 => _teamsClient.SendMessageToAllUsersInTenantAsync(null!, "tenant", _serviceUrl));
507 }
508
509 [Fact]
510 public async Task SendMessageToAllUsersInTenant_ThrowsOnNullTenantId()
511 {
512 var activity = new CoreActivity { Type = ActivityType.Message };
513 await Assert.ThrowsAsync<ArgumentNullException>(()
514 => _teamsClient.SendMessageToAllUsersInTenantAsync(activity, null!, _serviceUrl));
515 }
516
517 [Fact]
518 public async Task SendMessageToAllUsersInTeam_ThrowsOnNullActivity()
519 {
520 await Assert.ThrowsAsync<ArgumentNullException>(()
521 => _teamsClient.SendMessageToAllUsersInTeamAsync(null!, "team", "tenant", _serviceUrl));
522 }
523
524 [Fact]
525 public async Task SendMessageToAllUsersInTeam_ThrowsOnNullTeamId()
526 {
527 var activity = new CoreActivity { Type = ActivityType.Message };
528 await Assert.ThrowsAsync<ArgumentNullException>(()
529 => _teamsClient.SendMessageToAllUsersInTeamAsync(activity, null!, "tenant", _serviceUrl));
530 }
531
532 [Fact]
533 public async Task SendMessageToListOfChannels_ThrowsOnEmptyChannels()
534 {
535 var activity = new CoreActivity { Type = ActivityType.Message };
536 await Assert.ThrowsAsync<ArgumentException>(()
537 => _teamsClient.SendMessageToListOfChannelsAsync(activity, [], "tenant", _serviceUrl));
538 }
539
540 [Fact]
541 public async Task GetOperationState_ThrowsOnNullOperationId()
542 {
543 await Assert.ThrowsAsync<ArgumentNullException>(()
544 => _teamsClient.GetOperationStateAsync(null!, _serviceUrl));
545 }
546
547 [Fact]
548 public async Task GetPagedFailedEntries_ThrowsOnNullOperationId()
549 {
550 await Assert.ThrowsAsync<ArgumentNullException>(()
551 => _teamsClient.GetPagedFailedEntriesAsync(null!, _serviceUrl));
552 }
553
554 [Fact]
555 public async Task CancelOperation_ThrowsOnNullOperationId()
556 {
557 await Assert.ThrowsAsync<ArgumentNullException>(()
558 => _teamsClient.CancelOperationAsync(null!, _serviceUrl));
559 }
560
561 #endregion
562}
563