OSDN Git Service

Merge pull request #210 from opentween/csharp11
[opentween/open-tween.git] / OpenTween.Tests / Api / TwitterApiTest.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2016 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
4 //
5 // This file is part of OpenTween.
6 //
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
10 // any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 // for more details.
16 //
17 // You should have received a copy of the GNU General Public License along
18 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 // Boston, MA 02110-1301, USA.
21
22 using System;
23 using System.Collections.Generic;
24 using System.IO;
25 using System.Linq;
26 using System.Net.Http;
27 using System.Reflection;
28 using System.Runtime.InteropServices;
29 using System.Text;
30 using System.Threading.Tasks;
31 using Moq;
32 using OpenTween.Api.DataModel;
33 using OpenTween.Connection;
34 using Xunit;
35
36 namespace OpenTween.Api
37 {
38     public class TwitterApiTest
39     {
40         public TwitterApiTest()
41             => this.MyCommonSetup();
42
43         private void MyCommonSetup()
44         {
45             var mockAssembly = new Mock<_Assembly>();
46             mockAssembly.Setup(m => m.GetName()).Returns(new AssemblyName("OpenTween"));
47
48             MyCommon.EntryAssembly = mockAssembly.Object;
49         }
50
51         [Fact]
52         public void Initialize_Test()
53         {
54             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
55             Assert.Null(twitterApi.ApiConnection);
56
57             twitterApi.Initialize("*** AccessToken ***", "*** AccessSecret ***", userId: 100L, screenName: "hogehoge");
58
59             Assert.IsType<TwitterApiConnection>(twitterApi.ApiConnection);
60
61             var apiConnection = (TwitterApiConnection)twitterApi.ApiConnection!;
62             Assert.Equal("*** AccessToken ***", apiConnection.AccessToken);
63             Assert.Equal("*** AccessSecret ***", apiConnection.AccessSecret);
64
65             Assert.Equal(100L, twitterApi.CurrentUserId);
66             Assert.Equal("hogehoge", twitterApi.CurrentScreenName);
67
68             // 複数回 Initialize を実行した場合は新たに TwitterApiConnection が生成される
69             twitterApi.Initialize("*** AccessToken2 ***", "*** AccessSecret2 ***", userId: 200L, screenName: "foobar");
70
71             var oldApiConnection = apiConnection;
72             Assert.True(oldApiConnection.IsDisposed);
73
74             Assert.IsType<TwitterApiConnection>(twitterApi.ApiConnection);
75
76             apiConnection = (TwitterApiConnection)twitterApi.ApiConnection!;
77             Assert.Equal("*** AccessToken2 ***", apiConnection.AccessToken);
78             Assert.Equal("*** AccessSecret2 ***", apiConnection.AccessSecret);
79
80             Assert.Equal(200L, twitterApi.CurrentUserId);
81             Assert.Equal("foobar", twitterApi.CurrentScreenName);
82         }
83
84         [Fact]
85         public async Task StatusesHomeTimeline_Test()
86         {
87             var mock = new Mock<IApiConnection>();
88             mock.Setup(x =>
89                 x.GetAsync<TwitterStatus[]>(
90                     new Uri("statuses/home_timeline.json", UriKind.Relative),
91                     new Dictionary<string, string>
92                     {
93                             { "include_entities", "true" },
94                             { "include_ext_alt_text", "true" },
95                             { "tweet_mode", "extended" },
96                             { "count", "200" },
97                             { "max_id", "900" },
98                             { "since_id", "100" },
99                     },
100                     "/statuses/home_timeline")
101             )
102             .ReturnsAsync(Array.Empty<TwitterStatus>());
103
104             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
105             twitterApi.ApiConnection = mock.Object;
106
107             await twitterApi.StatusesHomeTimeline(200, maxId: 900L, sinceId: 100L)
108                 .ConfigureAwait(false);
109
110             mock.VerifyAll();
111         }
112
113         [Fact]
114         public async Task StatusesMentionsTimeline_Test()
115         {
116             var mock = new Mock<IApiConnection>();
117             mock.Setup(x =>
118                 x.GetAsync<TwitterStatus[]>(
119                     new Uri("statuses/mentions_timeline.json", UriKind.Relative),
120                     new Dictionary<string, string>
121                     {
122                             { "include_entities", "true" },
123                             { "include_ext_alt_text", "true" },
124                             { "tweet_mode", "extended" },
125                             { "count", "200" },
126                             { "max_id", "900" },
127                             { "since_id", "100" },
128                     },
129                     "/statuses/mentions_timeline")
130             )
131             .ReturnsAsync(Array.Empty<TwitterStatus>());
132
133             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
134             twitterApi.ApiConnection = mock.Object;
135
136             await twitterApi.StatusesMentionsTimeline(200, maxId: 900L, sinceId: 100L)
137                 .ConfigureAwait(false);
138
139             mock.VerifyAll();
140         }
141
142         [Fact]
143         public async Task StatusesUserTimeline_Test()
144         {
145             var mock = new Mock<IApiConnection>();
146             mock.Setup(x =>
147                 x.GetAsync<TwitterStatus[]>(
148                     new Uri("statuses/user_timeline.json", UriKind.Relative),
149                     new Dictionary<string, string>
150                     {
151                             { "screen_name", "twitterapi" },
152                             { "include_rts", "true" },
153                             { "include_entities", "true" },
154                             { "include_ext_alt_text", "true" },
155                             { "tweet_mode", "extended" },
156                             { "count", "200" },
157                             { "max_id", "900" },
158                             { "since_id", "100" },
159                     },
160                     "/statuses/user_timeline")
161             )
162             .ReturnsAsync(Array.Empty<TwitterStatus>());
163
164             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
165             twitterApi.ApiConnection = mock.Object;
166
167             await twitterApi.StatusesUserTimeline("twitterapi", count: 200, maxId: 900L, sinceId: 100L)
168                 .ConfigureAwait(false);
169
170             mock.VerifyAll();
171         }
172
173         [Fact]
174         public async Task StatusesShow_Test()
175         {
176             var mock = new Mock<IApiConnection>();
177             mock.Setup(x =>
178                 x.GetAsync<TwitterStatus>(
179                     new Uri("statuses/show.json", UriKind.Relative),
180                     new Dictionary<string, string>
181                     {
182                             { "id", "100" },
183                             { "include_entities", "true" },
184                             { "include_ext_alt_text", "true" },
185                             { "tweet_mode", "extended" },
186                     },
187                     "/statuses/show/:id")
188             )
189             .ReturnsAsync(new TwitterStatus { Id = 100L });
190
191             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
192             twitterApi.ApiConnection = mock.Object;
193
194             await twitterApi.StatusesShow(statusId: new("100"))
195                 .ConfigureAwait(false);
196
197             mock.VerifyAll();
198         }
199
200         [Fact]
201         public async Task StatusesLookup_Test()
202         {
203             var mock = new Mock<IApiConnection>();
204             mock.Setup(x =>
205                 x.GetAsync<TwitterStatus[]>(
206                     new Uri("statuses/lookup.json", UriKind.Relative),
207                     new Dictionary<string, string>
208                     {
209                         { "id", "100,200" },
210                         { "include_entities", "true" },
211                         { "include_ext_alt_text", "true" },
212                         { "tweet_mode", "extended" },
213                     },
214                     "/statuses/lookup"
215                 )
216             )
217             .ReturnsAsync(Array.Empty<TwitterStatus>());
218
219             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
220             twitterApi.ApiConnection = mock.Object;
221
222             await twitterApi.StatusesLookup(statusIds: new[] { "100", "200" })
223                 .ConfigureAwait(false);
224
225             mock.VerifyAll();
226         }
227
228         [Fact]
229         public async Task StatusesUpdate_Test()
230         {
231             var mock = new Mock<IApiConnection>();
232             mock.Setup(x =>
233                 x.PostLazyAsync<TwitterStatus>(
234                     new Uri("statuses/update.json", UriKind.Relative),
235                     new Dictionary<string, string>
236                     {
237                             { "status", "hogehoge" },
238                             { "include_entities", "true" },
239                             { "include_ext_alt_text", "true" },
240                             { "tweet_mode", "extended" },
241                             { "in_reply_to_status_id", "100" },
242                             { "media_ids", "10,20" },
243                             { "auto_populate_reply_metadata", "true" },
244                             { "exclude_reply_user_ids", "100,200" },
245                             { "attachment_url", "https://twitter.com/twitterapi/status/22634515958" },
246                     })
247             )
248             .ReturnsAsync(LazyJson.Create(new TwitterStatus()));
249
250             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
251             twitterApi.ApiConnection = mock.Object;
252
253             await twitterApi.StatusesUpdate(
254                     "hogehoge",
255                     replyToId: new("100"),
256                     mediaIds: new[] { 10L, 20L },
257                     autoPopulateReplyMetadata: true,
258                     excludeReplyUserIds: new[] { 100L, 200L },
259                     attachmentUrl: "https://twitter.com/twitterapi/status/22634515958"
260                 )
261                 .IgnoreResponse()
262                 .ConfigureAwait(false);
263
264             mock.VerifyAll();
265         }
266
267         [Fact]
268         public async Task StatusesUpdate_ExcludeReplyUserIdsEmptyTest()
269         {
270             var mock = new Mock<IApiConnection>();
271             mock.Setup(x =>
272                 x.PostLazyAsync<TwitterStatus>(
273                     new Uri("statuses/update.json", UriKind.Relative),
274                     new Dictionary<string, string>
275                     {
276                         { "status", "hogehoge" },
277                         { "include_entities", "true" },
278                         { "include_ext_alt_text", "true" },
279                         { "tweet_mode", "extended" },
280                         // exclude_reply_user_ids は空の場合には送信されない
281                     })
282             )
283             .ReturnsAsync(LazyJson.Create(new TwitterStatus()));
284
285             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
286             twitterApi.ApiConnection = mock.Object;
287
288             await twitterApi.StatusesUpdate("hogehoge", replyToId: null, mediaIds: null, excludeReplyUserIds: Array.Empty<long>())
289                 .IgnoreResponse()
290                 .ConfigureAwait(false);
291
292             mock.VerifyAll();
293         }
294
295         [Fact]
296         public async Task StatusesDestroy_Test()
297         {
298             var mock = new Mock<IApiConnection>();
299             mock.Setup(x =>
300                 x.PostLazyAsync<TwitterStatus>(
301                     new Uri("statuses/destroy.json", UriKind.Relative),
302                     new Dictionary<string, string> { { "id", "100" } })
303             )
304             .ReturnsAsync(LazyJson.Create(new TwitterStatus { Id = 100L }));
305
306             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
307             twitterApi.ApiConnection = mock.Object;
308
309             await twitterApi.StatusesDestroy(statusId: new("100"))
310                 .IgnoreResponse()
311                 .ConfigureAwait(false);
312
313             mock.VerifyAll();
314         }
315
316         [Fact]
317         public async Task StatusesRetweet_Test()
318         {
319             var mock = new Mock<IApiConnection>();
320             mock.Setup(x =>
321                 x.PostLazyAsync<TwitterStatus>(
322                     new Uri("statuses/retweet.json", UriKind.Relative),
323                     new Dictionary<string, string>
324                     {
325                             { "id", "100" },
326                             { "include_entities", "true" },
327                             { "include_ext_alt_text", "true" },
328                             { "tweet_mode", "extended" },
329                     })
330             )
331             .ReturnsAsync(LazyJson.Create(new TwitterStatus()));
332
333             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
334             twitterApi.ApiConnection = mock.Object;
335
336             await twitterApi.StatusesRetweet(new("100"))
337                 .IgnoreResponse()
338                 .ConfigureAwait(false);
339
340             mock.VerifyAll();
341         }
342
343         [Fact]
344         public async Task SearchTweets_Test()
345         {
346             var mock = new Mock<IApiConnection>();
347             mock.Setup(x =>
348                 x.GetAsync<TwitterSearchResult>(
349                     new Uri("search/tweets.json", UriKind.Relative),
350                     new Dictionary<string, string>
351                     {
352                             { "q", "from:twitterapi" },
353                             { "result_type", "recent" },
354                             { "include_entities", "true" },
355                             { "include_ext_alt_text", "true" },
356                             { "tweet_mode", "extended" },
357                             { "lang", "en" },
358                             { "count", "200" },
359                             { "max_id", "900" },
360                             { "since_id", "100" },
361                     },
362                     "/search/tweets")
363             )
364             .ReturnsAsync(new TwitterSearchResult());
365
366             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
367             twitterApi.ApiConnection = mock.Object;
368
369             await twitterApi.SearchTweets("from:twitterapi", "en", count: 200, maxId: 900L, sinceId: 100L)
370                 .ConfigureAwait(false);
371
372             mock.VerifyAll();
373         }
374
375         [Fact]
376         public async Task ListsOwnerships_Test()
377         {
378             var mock = new Mock<IApiConnection>();
379             mock.Setup(x =>
380                 x.GetAsync<TwitterLists>(
381                     new Uri("lists/ownerships.json", UriKind.Relative),
382                     new Dictionary<string, string>
383                     {
384                             { "screen_name", "twitterapi" },
385                             { "cursor", "-1" },
386                             { "count", "100" },
387                     },
388                     "/lists/ownerships")
389             )
390             .ReturnsAsync(new TwitterLists());
391
392             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
393             twitterApi.ApiConnection = mock.Object;
394
395             await twitterApi.ListsOwnerships("twitterapi", cursor: -1L, count: 100)
396                 .ConfigureAwait(false);
397
398             mock.VerifyAll();
399         }
400
401         [Fact]
402         public async Task ListsSubscriptions_Test()
403         {
404             var mock = new Mock<IApiConnection>();
405             mock.Setup(x =>
406                 x.GetAsync<TwitterLists>(
407                     new Uri("lists/subscriptions.json", UriKind.Relative),
408                     new Dictionary<string, string>
409                     {
410                             { "screen_name", "twitterapi" },
411                             { "cursor", "-1" },
412                             { "count", "100" },
413                     },
414                     "/lists/subscriptions")
415             )
416             .ReturnsAsync(new TwitterLists());
417
418             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
419             twitterApi.ApiConnection = mock.Object;
420
421             await twitterApi.ListsSubscriptions("twitterapi", cursor: -1L, count: 100)
422                 .ConfigureAwait(false);
423
424             mock.VerifyAll();
425         }
426
427         [Fact]
428         public async Task ListsMemberships_Test()
429         {
430             var mock = new Mock<IApiConnection>();
431             mock.Setup(x =>
432                 x.GetAsync<TwitterLists>(
433                     new Uri("lists/memberships.json", UriKind.Relative),
434                     new Dictionary<string, string>
435                     {
436                             { "screen_name", "twitterapi" },
437                             { "cursor", "-1" },
438                             { "count", "100" },
439                             { "filter_to_owned_lists", "true" },
440                     },
441                     "/lists/memberships")
442             )
443             .ReturnsAsync(new TwitterLists());
444
445             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
446             twitterApi.ApiConnection = mock.Object;
447
448             await twitterApi.ListsMemberships("twitterapi", cursor: -1L, count: 100, filterToOwnedLists: true)
449                 .ConfigureAwait(false);
450
451             mock.VerifyAll();
452         }
453
454         [Fact]
455         public async Task ListsCreate_Test()
456         {
457             var mock = new Mock<IApiConnection>();
458             mock.Setup(x =>
459                 x.PostLazyAsync<TwitterList>(
460                     new Uri("lists/create.json", UriKind.Relative),
461                     new Dictionary<string, string>
462                     {
463                             { "name", "hogehoge" },
464                             { "description", "aaaa" },
465                             { "mode", "private" },
466                     })
467             )
468             .ReturnsAsync(LazyJson.Create(new TwitterList()));
469
470             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
471             twitterApi.ApiConnection = mock.Object;
472
473             await twitterApi.ListsCreate("hogehoge", description: "aaaa", @private: true)
474                 .IgnoreResponse()
475                 .ConfigureAwait(false);
476
477             mock.VerifyAll();
478         }
479
480         [Fact]
481         public async Task ListsUpdate_Test()
482         {
483             var mock = new Mock<IApiConnection>();
484             mock.Setup(x =>
485                 x.PostLazyAsync<TwitterList>(
486                     new Uri("lists/update.json", UriKind.Relative),
487                     new Dictionary<string, string>
488                     {
489                             { "list_id", "12345" },
490                             { "name", "hogehoge" },
491                             { "description", "aaaa" },
492                             { "mode", "private" },
493                     })
494             )
495             .ReturnsAsync(LazyJson.Create(new TwitterList()));
496
497             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
498             twitterApi.ApiConnection = mock.Object;
499
500             await twitterApi.ListsUpdate(12345L, name: "hogehoge", description: "aaaa", @private: true)
501                 .IgnoreResponse()
502                 .ConfigureAwait(false);
503
504             mock.VerifyAll();
505         }
506
507         [Fact]
508         public async Task ListsDestroy_Test()
509         {
510             var mock = new Mock<IApiConnection>();
511             mock.Setup(x =>
512                 x.PostLazyAsync<TwitterList>(
513                     new Uri("lists/destroy.json", UriKind.Relative),
514                     new Dictionary<string, string>
515                     {
516                             { "list_id", "12345" },
517                     })
518             )
519             .ReturnsAsync(LazyJson.Create(new TwitterList()));
520
521             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
522             twitterApi.ApiConnection = mock.Object;
523
524             await twitterApi.ListsDestroy(12345L)
525                 .IgnoreResponse()
526                 .ConfigureAwait(false);
527
528             mock.VerifyAll();
529         }
530
531         [Fact]
532         public async Task ListsStatuses_Test()
533         {
534             var mock = new Mock<IApiConnection>();
535             mock.Setup(x =>
536                 x.GetAsync<TwitterStatus[]>(
537                     new Uri("lists/statuses.json", UriKind.Relative),
538                     new Dictionary<string, string>
539                     {
540                             { "list_id", "12345" },
541                             { "include_entities", "true" },
542                             { "include_ext_alt_text", "true" },
543                             { "tweet_mode", "extended" },
544                             { "count", "200" },
545                             { "max_id", "900" },
546                             { "since_id", "100" },
547                             { "include_rts", "true" },
548                     },
549                     "/lists/statuses")
550             )
551             .ReturnsAsync(Array.Empty<TwitterStatus>());
552
553             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
554             twitterApi.ApiConnection = mock.Object;
555
556             await twitterApi.ListsStatuses(12345L, count: 200, maxId: 900L, sinceId: 100L, includeRTs: true)
557                 .ConfigureAwait(false);
558
559             mock.VerifyAll();
560         }
561
562         [Fact]
563         public async Task ListsMembers_Test()
564         {
565             var mock = new Mock<IApiConnection>();
566             mock.Setup(x =>
567                 x.GetAsync<TwitterUsers>(
568                     new Uri("lists/members.json", UriKind.Relative),
569                     new Dictionary<string, string>
570                     {
571                             { "list_id", "12345" },
572                             { "include_entities", "true" },
573                             { "include_ext_alt_text", "true" },
574                             { "tweet_mode", "extended" },
575                             { "cursor", "-1" },
576                     },
577                     "/lists/members")
578             )
579             .ReturnsAsync(new TwitterUsers());
580
581             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
582             twitterApi.ApiConnection = mock.Object;
583
584             await twitterApi.ListsMembers(12345L, cursor: -1)
585                 .ConfigureAwait(false);
586
587             mock.VerifyAll();
588         }
589
590         [Fact]
591         public async Task ListsMembersShow_Test()
592         {
593             var mock = new Mock<IApiConnection>();
594             mock.Setup(x =>
595                 x.GetAsync<TwitterUser>(
596                     new Uri("lists/members/show.json", UriKind.Relative),
597                     new Dictionary<string, string>
598                     {
599                             { "list_id", "12345" },
600                             { "screen_name", "twitterapi" },
601                             { "include_entities", "true" },
602                             { "include_ext_alt_text", "true" },
603                             { "tweet_mode", "extended" },
604                     },
605                     "/lists/members/show")
606             )
607             .ReturnsAsync(new TwitterUser());
608
609             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
610             twitterApi.ApiConnection = mock.Object;
611
612             await twitterApi.ListsMembersShow(12345L, "twitterapi")
613                 .ConfigureAwait(false);
614
615             mock.VerifyAll();
616         }
617
618         [Fact]
619         public async Task ListsMembersCreate_Test()
620         {
621             var mock = new Mock<IApiConnection>();
622             mock.Setup(x =>
623                 x.PostLazyAsync<TwitterUser>(
624                     new Uri("lists/members/create.json", UriKind.Relative),
625                     new Dictionary<string, string>
626                     {
627                             { "list_id", "12345" },
628                             { "screen_name", "twitterapi" },
629                             { "include_entities", "true" },
630                             { "include_ext_alt_text", "true" },
631                             { "tweet_mode", "extended" },
632                     })
633             )
634             .ReturnsAsync(LazyJson.Create(new TwitterUser()));
635
636             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
637             twitterApi.ApiConnection = mock.Object;
638
639             await twitterApi.ListsMembersCreate(12345L, "twitterapi")
640                 .IgnoreResponse()
641                 .ConfigureAwait(false);
642
643             mock.VerifyAll();
644         }
645
646         [Fact]
647         public async Task ListsMembersDestroy_Test()
648         {
649             var mock = new Mock<IApiConnection>();
650             mock.Setup(x =>
651                 x.PostLazyAsync<TwitterUser>(
652                     new Uri("lists/members/destroy.json", UriKind.Relative),
653                     new Dictionary<string, string>
654                     {
655                             { "list_id", "12345" },
656                             { "screen_name", "twitterapi" },
657                             { "include_entities", "true" },
658                             { "include_ext_alt_text", "true" },
659                             { "tweet_mode", "extended" },
660                     })
661             )
662             .ReturnsAsync(LazyJson.Create(new TwitterUser()));
663
664             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
665             twitterApi.ApiConnection = mock.Object;
666
667             await twitterApi.ListsMembersDestroy(12345L, "twitterapi")
668                 .IgnoreResponse()
669                 .ConfigureAwait(false);
670
671             mock.VerifyAll();
672         }
673
674         [Fact]
675         public async Task DirectMessagesEventsList_Test()
676         {
677             var mock = new Mock<IApiConnection>();
678             mock.Setup(x =>
679                 x.GetAsync<TwitterMessageEventList>(
680                     new Uri("direct_messages/events/list.json", UriKind.Relative),
681                     new Dictionary<string, string>
682                     {
683                             { "count", "50" },
684                             { "cursor", "12345abcdefg" },
685                     },
686                     "/direct_messages/events/list")
687             )
688             .ReturnsAsync(new TwitterMessageEventList());
689
690             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
691             twitterApi.ApiConnection = mock.Object;
692
693             await twitterApi.DirectMessagesEventsList(count: 50, cursor: "12345abcdefg")
694                 .ConfigureAwait(false);
695
696             mock.VerifyAll();
697         }
698
699         [Fact]
700         public async Task DirectMessagesEventsNew_Test()
701         {
702             var mock = new Mock<IApiConnection>();
703             var responseText = """
704                 {
705                   "event": {
706                     "type": "message_create",
707                     "message_create": {
708                       "target": {
709                         "recipient_id": "12345"
710                       },
711                       "message_data": {
712                         "text": "hogehoge",
713                         "attachment": {
714                           "type": "media",
715                           "media": {
716                             "id": "67890"
717                           }
718                         }
719                       }
720                     }
721                   }
722                 }
723                 """;
724             mock.Setup(x =>
725                 x.PostJsonAsync<TwitterMessageEventSingle>(
726                     new Uri("direct_messages/events/new.json", UriKind.Relative),
727                     responseText)
728             )
729             .ReturnsAsync(LazyJson.Create(new TwitterMessageEventSingle()));
730
731             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
732             twitterApi.ApiConnection = mock.Object;
733
734             await twitterApi.DirectMessagesEventsNew(recipientId: 12345L, text: "hogehoge", mediaId: 67890L)
735                 .ConfigureAwait(false);
736
737             mock.VerifyAll();
738         }
739
740         [Fact]
741         public async Task DirectMessagesEventsDestroy_Test()
742         {
743             var mock = new Mock<IApiConnection>();
744             mock.Setup(x =>
745                 x.DeleteAsync(
746                     new Uri("direct_messages/events/destroy.json?id=100", UriKind.Relative))
747             )
748             .Returns(Task.CompletedTask);
749
750             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
751             twitterApi.ApiConnection = mock.Object;
752
753             await twitterApi.DirectMessagesEventsDestroy(eventId: new("100"))
754                 .ConfigureAwait(false);
755
756             mock.VerifyAll();
757         }
758
759         [Fact]
760         public async Task UsersShow_Test()
761         {
762             var mock = new Mock<IApiConnection>();
763             mock.Setup(x =>
764                 x.GetAsync<TwitterUser>(
765                     new Uri("users/show.json", UriKind.Relative),
766                     new Dictionary<string, string>
767                     {
768                             { "screen_name", "twitterapi" },
769                             { "include_entities", "true" },
770                             { "include_ext_alt_text", "true" },
771                             { "tweet_mode", "extended" },
772                     },
773                     "/users/show/:id")
774             )
775             .ReturnsAsync(new TwitterUser { ScreenName = "twitterapi" });
776
777             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
778             twitterApi.ApiConnection = mock.Object;
779
780             await twitterApi.UsersShow(screenName: "twitterapi")
781                 .ConfigureAwait(false);
782
783             mock.VerifyAll();
784         }
785
786         [Fact]
787         public async Task UsersLookup_Test()
788         {
789             var mock = new Mock<IApiConnection>();
790             mock.Setup(x =>
791                 x.GetAsync<TwitterUser[]>(
792                     new Uri("users/lookup.json", UriKind.Relative),
793                     new Dictionary<string, string>
794                     {
795                             { "user_id", "11111,22222" },
796                             { "include_entities", "true" },
797                             { "include_ext_alt_text", "true" },
798                             { "tweet_mode", "extended" },
799                     },
800                     "/users/lookup")
801             )
802             .ReturnsAsync(Array.Empty<TwitterUser>());
803
804             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
805             twitterApi.ApiConnection = mock.Object;
806
807             await twitterApi.UsersLookup(userIds: new[] { "11111", "22222" })
808                 .ConfigureAwait(false);
809
810             mock.VerifyAll();
811         }
812
813         [Fact]
814         public async Task UsersReportSpam_Test()
815         {
816             var mock = new Mock<IApiConnection>();
817             mock.Setup(x =>
818                 x.PostLazyAsync<TwitterUser>(
819                     new Uri("users/report_spam.json", UriKind.Relative),
820                     new Dictionary<string, string>
821                     {
822                             { "screen_name", "twitterapi" },
823                             { "tweet_mode", "extended" },
824                     })
825             )
826             .ReturnsAsync(LazyJson.Create(new TwitterUser { ScreenName = "twitterapi" }));
827
828             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
829             twitterApi.ApiConnection = mock.Object;
830
831             await twitterApi.UsersReportSpam(screenName: "twitterapi")
832                 .IgnoreResponse()
833                 .ConfigureAwait(false);
834
835             mock.VerifyAll();
836         }
837
838         [Fact]
839         public async Task FavoritesList_Test()
840         {
841             var mock = new Mock<IApiConnection>();
842             mock.Setup(x =>
843                 x.GetAsync<TwitterStatus[]>(
844                     new Uri("favorites/list.json", UriKind.Relative),
845                     new Dictionary<string, string>
846                     {
847                             { "include_entities", "true" },
848                             { "include_ext_alt_text", "true" },
849                             { "tweet_mode", "extended" },
850                             { "count", "200" },
851                             { "max_id", "900" },
852                             { "since_id", "100" },
853                     },
854                     "/favorites/list")
855             )
856             .ReturnsAsync(Array.Empty<TwitterStatus>());
857
858             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
859             twitterApi.ApiConnection = mock.Object;
860
861             await twitterApi.FavoritesList(200, maxId: 900L, sinceId: 100L)
862                 .ConfigureAwait(false);
863
864             mock.VerifyAll();
865         }
866
867         [Fact]
868         public async Task FavoritesCreate_Test()
869         {
870             var mock = new Mock<IApiConnection>();
871             mock.Setup(x =>
872                 x.PostLazyAsync<TwitterStatus>(
873                     new Uri("favorites/create.json", UriKind.Relative),
874                     new Dictionary<string, string>
875                     {
876                             { "id", "100" },
877                             { "tweet_mode", "extended" },
878                     })
879             )
880             .ReturnsAsync(LazyJson.Create(new TwitterStatus { Id = 100L }));
881
882             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
883             twitterApi.ApiConnection = mock.Object;
884
885             await twitterApi.FavoritesCreate(statusId: new("100"))
886                 .IgnoreResponse()
887                 .ConfigureAwait(false);
888
889             mock.VerifyAll();
890         }
891
892         [Fact]
893         public async Task FavoritesDestroy_Test()
894         {
895             var mock = new Mock<IApiConnection>();
896             mock.Setup(x =>
897                 x.PostLazyAsync<TwitterStatus>(
898                     new Uri("favorites/destroy.json", UriKind.Relative),
899                     new Dictionary<string, string>
900                     {
901                             { "id", "100" },
902                             { "tweet_mode", "extended" },
903                     })
904             )
905             .ReturnsAsync(LazyJson.Create(new TwitterStatus { Id = 100L }));
906
907             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
908             twitterApi.ApiConnection = mock.Object;
909
910             await twitterApi.FavoritesDestroy(statusId: new("100"))
911                 .IgnoreResponse()
912                 .ConfigureAwait(false);
913
914             mock.VerifyAll();
915         }
916
917         [Fact]
918         public async Task FriendshipsShow_Test()
919         {
920             var mock = new Mock<IApiConnection>();
921             mock.Setup(x =>
922                 x.GetAsync<TwitterFriendship>(
923                     new Uri("friendships/show.json", UriKind.Relative),
924                     new Dictionary<string, string> { { "source_screen_name", "twitter" }, { "target_screen_name", "twitterapi" } },
925                     "/friendships/show")
926             )
927             .ReturnsAsync(new TwitterFriendship());
928
929             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
930             twitterApi.ApiConnection = mock.Object;
931
932             await twitterApi.FriendshipsShow(sourceScreenName: "twitter", targetScreenName: "twitterapi")
933                 .ConfigureAwait(false);
934
935             mock.VerifyAll();
936         }
937
938         [Fact]
939         public async Task FriendshipsCreate_Test()
940         {
941             var mock = new Mock<IApiConnection>();
942             mock.Setup(x =>
943                 x.PostLazyAsync<TwitterFriendship>(
944                     new Uri("friendships/create.json", UriKind.Relative),
945                     new Dictionary<string, string> { { "screen_name", "twitterapi" } })
946             )
947             .ReturnsAsync(LazyJson.Create(new TwitterFriendship()));
948
949             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
950             twitterApi.ApiConnection = mock.Object;
951
952             await twitterApi.FriendshipsCreate(screenName: "twitterapi")
953                 .IgnoreResponse()
954                 .ConfigureAwait(false);
955
956             mock.VerifyAll();
957         }
958
959         [Fact]
960         public async Task FriendshipsDestroy_Test()
961         {
962             var mock = new Mock<IApiConnection>();
963             mock.Setup(x =>
964                 x.PostLazyAsync<TwitterFriendship>(
965                     new Uri("friendships/destroy.json", UriKind.Relative),
966                     new Dictionary<string, string> { { "screen_name", "twitterapi" } })
967             )
968             .ReturnsAsync(LazyJson.Create(new TwitterFriendship()));
969
970             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
971             twitterApi.ApiConnection = mock.Object;
972
973             await twitterApi.FriendshipsDestroy(screenName: "twitterapi")
974                 .IgnoreResponse()
975                 .ConfigureAwait(false);
976
977             mock.VerifyAll();
978         }
979
980         [Fact]
981         public async Task NoRetweetIds_Test()
982         {
983             var mock = new Mock<IApiConnection>();
984             mock.Setup(x =>
985                 x.GetAsync<long[]>(
986                     new Uri("friendships/no_retweets/ids.json", UriKind.Relative),
987                     null,
988                     "/friendships/no_retweets/ids")
989             )
990             .ReturnsAsync(Array.Empty<long>());
991
992             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
993             twitterApi.ApiConnection = mock.Object;
994
995             await twitterApi.NoRetweetIds()
996                 .ConfigureAwait(false);
997
998             mock.VerifyAll();
999         }
1000
1001         [Fact]
1002         public async Task FollowersIds_Test()
1003         {
1004             var mock = new Mock<IApiConnection>();
1005             mock.Setup(x =>
1006                 x.GetAsync<TwitterIds>(
1007                     new Uri("followers/ids.json", UriKind.Relative),
1008                     new Dictionary<string, string> { { "cursor", "-1" } },
1009                     "/followers/ids")
1010             )
1011             .ReturnsAsync(new TwitterIds());
1012
1013             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1014             twitterApi.ApiConnection = mock.Object;
1015
1016             await twitterApi.FollowersIds(cursor: -1L)
1017                 .ConfigureAwait(false);
1018
1019             mock.VerifyAll();
1020         }
1021
1022         [Fact]
1023         public async Task MutesUsersIds_Test()
1024         {
1025             var mock = new Mock<IApiConnection>();
1026             mock.Setup(x =>
1027                 x.GetAsync<TwitterIds>(
1028                     new Uri("mutes/users/ids.json", UriKind.Relative),
1029                     new Dictionary<string, string> { { "cursor", "-1" } },
1030                     "/mutes/users/ids")
1031             )
1032             .ReturnsAsync(new TwitterIds());
1033
1034             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1035             twitterApi.ApiConnection = mock.Object;
1036
1037             await twitterApi.MutesUsersIds(cursor: -1L)
1038                 .ConfigureAwait(false);
1039
1040             mock.VerifyAll();
1041         }
1042
1043         [Fact]
1044         public async Task BlocksIds_Test()
1045         {
1046             var mock = new Mock<IApiConnection>();
1047             mock.Setup(x =>
1048                 x.GetAsync<TwitterIds>(
1049                     new Uri("blocks/ids.json", UriKind.Relative),
1050                     new Dictionary<string, string> { { "cursor", "-1" } },
1051                     "/blocks/ids")
1052             )
1053             .ReturnsAsync(new TwitterIds());
1054
1055             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1056             twitterApi.ApiConnection = mock.Object;
1057
1058             await twitterApi.BlocksIds(cursor: -1L)
1059                 .ConfigureAwait(false);
1060
1061             mock.VerifyAll();
1062         }
1063
1064         [Fact]
1065         public async Task BlocksCreate_Test()
1066         {
1067             var mock = new Mock<IApiConnection>();
1068             mock.Setup(x =>
1069                 x.PostLazyAsync<TwitterUser>(
1070                     new Uri("blocks/create.json", UriKind.Relative),
1071                     new Dictionary<string, string>
1072                     {
1073                             { "screen_name", "twitterapi" },
1074                             { "tweet_mode", "extended" },
1075                     })
1076             )
1077             .ReturnsAsync(LazyJson.Create(new TwitterUser()));
1078
1079             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1080             twitterApi.ApiConnection = mock.Object;
1081
1082             await twitterApi.BlocksCreate(screenName: "twitterapi")
1083                 .IgnoreResponse()
1084                 .ConfigureAwait(false);
1085
1086             mock.VerifyAll();
1087         }
1088
1089         [Fact]
1090         public async Task BlocksDestroy_Test()
1091         {
1092             var mock = new Mock<IApiConnection>();
1093             mock.Setup(x =>
1094                 x.PostLazyAsync<TwitterUser>(
1095                     new Uri("blocks/destroy.json", UriKind.Relative),
1096                     new Dictionary<string, string>
1097                     {
1098                             { "screen_name", "twitterapi" },
1099                             { "tweet_mode", "extended" },
1100                     })
1101             )
1102             .ReturnsAsync(LazyJson.Create(new TwitterUser()));
1103
1104             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1105             twitterApi.ApiConnection = mock.Object;
1106
1107             await twitterApi.BlocksDestroy(screenName: "twitterapi")
1108                 .IgnoreResponse()
1109                 .ConfigureAwait(false);
1110
1111             mock.VerifyAll();
1112         }
1113
1114         [Fact]
1115         public async Task AccountVerifyCredentials_Test()
1116         {
1117             var mock = new Mock<IApiConnection>();
1118             mock.Setup(x =>
1119                 x.GetAsync<TwitterUser>(
1120                     new Uri("account/verify_credentials.json", UriKind.Relative),
1121                     new Dictionary<string, string>
1122                     {
1123                             { "include_entities", "true" },
1124                             { "include_ext_alt_text", "true" },
1125                             { "tweet_mode", "extended" },
1126                     },
1127                     "/account/verify_credentials")
1128             )
1129             .ReturnsAsync(new TwitterUser
1130             {
1131                 Id = 100L,
1132                 ScreenName = "opentween",
1133             });
1134
1135             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1136             twitterApi.ApiConnection = mock.Object;
1137
1138             await twitterApi.AccountVerifyCredentials()
1139                 .ConfigureAwait(false);
1140
1141             Assert.Equal(100L, twitterApi.CurrentUserId);
1142             Assert.Equal("opentween", twitterApi.CurrentScreenName);
1143
1144             mock.VerifyAll();
1145         }
1146
1147         [Fact]
1148         public async Task AccountUpdateProfile_Test()
1149         {
1150             var mock = new Mock<IApiConnection>();
1151             mock.Setup(x =>
1152                 x.PostLazyAsync<TwitterUser>(
1153                     new Uri("account/update_profile.json", UriKind.Relative),
1154                     new Dictionary<string, string>
1155                     {
1156                             { "include_entities", "true" },
1157                             { "include_ext_alt_text", "true" },
1158                             { "tweet_mode", "extended" },
1159                             { "name", "Name" },
1160                             { "url", "http://example.com/" },
1161                             { "location", "Location" },
1162                             { "description", "&lt;script&gt;alert(1)&lt;/script&gt;" },
1163                     })
1164             )
1165             .ReturnsAsync(LazyJson.Create(new TwitterUser()));
1166
1167             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1168             twitterApi.ApiConnection = mock.Object;
1169
1170             await twitterApi.AccountUpdateProfile(name: "Name", url: "http://example.com/", location: "Location", description: "<script>alert(1)</script>")
1171                 .IgnoreResponse()
1172                 .ConfigureAwait(false);
1173
1174             mock.VerifyAll();
1175         }
1176
1177         [Fact]
1178         public async Task AccountUpdateProfileImage_Test()
1179         {
1180             using var image = TestUtils.CreateDummyImage();
1181             using var media = new MemoryImageMediaItem(image);
1182             var mock = new Mock<IApiConnection>();
1183             mock.Setup(x =>
1184                 x.PostLazyAsync<TwitterUser>(
1185                     new Uri("account/update_profile_image.json", UriKind.Relative),
1186                     new Dictionary<string, string>
1187                     {
1188                             { "include_entities", "true" },
1189                             { "include_ext_alt_text", "true" },
1190                             { "tweet_mode", "extended" },
1191                     },
1192                     new Dictionary<string, IMediaItem> { { "image", media } })
1193             )
1194             .ReturnsAsync(LazyJson.Create(new TwitterUser()));
1195
1196             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1197             twitterApi.ApiConnection = mock.Object;
1198
1199             await twitterApi.AccountUpdateProfileImage(media)
1200                 .IgnoreResponse()
1201                 .ConfigureAwait(false);
1202
1203             mock.VerifyAll();
1204         }
1205
1206         [Fact]
1207         public async Task ApplicationRateLimitStatus_Test()
1208         {
1209             var mock = new Mock<IApiConnection>();
1210             mock.Setup(x =>
1211                 x.GetAsync<TwitterRateLimits>(
1212                     new Uri("application/rate_limit_status.json", UriKind.Relative),
1213                     null,
1214                     "/application/rate_limit_status")
1215             )
1216             .ReturnsAsync(new TwitterRateLimits());
1217
1218             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1219             twitterApi.ApiConnection = mock.Object;
1220
1221             await twitterApi.ApplicationRateLimitStatus()
1222                 .ConfigureAwait(false);
1223
1224             mock.VerifyAll();
1225         }
1226
1227         [Fact]
1228         public async Task Configuration_Test()
1229         {
1230             var mock = new Mock<IApiConnection>();
1231             mock.Setup(x =>
1232                 x.GetAsync<TwitterConfiguration>(
1233                     new Uri("help/configuration.json", UriKind.Relative),
1234                     null,
1235                     "/help/configuration")
1236             )
1237             .ReturnsAsync(new TwitterConfiguration());
1238
1239             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1240             twitterApi.ApiConnection = mock.Object;
1241
1242             await twitterApi.Configuration()
1243                 .ConfigureAwait(false);
1244
1245             mock.VerifyAll();
1246         }
1247
1248         [Fact]
1249         public async Task MediaUploadInit_Test()
1250         {
1251             var mock = new Mock<IApiConnection>();
1252             mock.Setup(x =>
1253                 x.PostLazyAsync<TwitterUploadMediaInit>(
1254                     new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
1255                     new Dictionary<string, string>
1256                     {
1257                             { "command", "INIT" },
1258                             { "total_bytes", "123456" },
1259                             { "media_type", "image/png" },
1260                             { "media_category", "dm_image" },
1261                     })
1262             )
1263             .ReturnsAsync(LazyJson.Create(new TwitterUploadMediaInit()));
1264
1265             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1266             twitterApi.ApiConnection = mock.Object;
1267
1268             await twitterApi.MediaUploadInit(totalBytes: 123456L, mediaType: "image/png", mediaCategory: "dm_image")
1269                 .IgnoreResponse()
1270                 .ConfigureAwait(false);
1271
1272             mock.VerifyAll();
1273         }
1274
1275         [Fact]
1276         public async Task MediaUploadAppend_Test()
1277         {
1278             using var image = TestUtils.CreateDummyImage();
1279             using var media = new MemoryImageMediaItem(image);
1280             var mock = new Mock<IApiConnection>();
1281             mock.Setup(x =>
1282                 x.PostAsync(
1283                     new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
1284                     new Dictionary<string, string>
1285                     {
1286                             { "command", "APPEND" },
1287                             { "media_id", "11111" },
1288                             { "segment_index", "1" },
1289                     },
1290                     new Dictionary<string, IMediaItem> { { "media", media } })
1291             )
1292             .Returns(Task.CompletedTask);
1293
1294             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1295             twitterApi.ApiConnection = mock.Object;
1296
1297             await twitterApi.MediaUploadAppend(mediaId: 11111L, segmentIndex: 1, media: media)
1298                 .ConfigureAwait(false);
1299
1300             mock.VerifyAll();
1301         }
1302
1303         [Fact]
1304         public async Task MediaUploadFinalize_Test()
1305         {
1306             var mock = new Mock<IApiConnection>();
1307             mock.Setup(x =>
1308                 x.PostLazyAsync<TwitterUploadMediaResult>(
1309                     new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
1310                     new Dictionary<string, string>
1311                     {
1312                             { "command", "FINALIZE" },
1313                             { "media_id", "11111" },
1314                     })
1315             )
1316             .ReturnsAsync(LazyJson.Create(new TwitterUploadMediaResult()));
1317
1318             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1319             twitterApi.ApiConnection = mock.Object;
1320
1321             await twitterApi.MediaUploadFinalize(mediaId: 11111L)
1322                 .IgnoreResponse()
1323                 .ConfigureAwait(false);
1324
1325             mock.VerifyAll();
1326         }
1327
1328         [Fact]
1329         public async Task MediaUploadStatus_Test()
1330         {
1331             var mock = new Mock<IApiConnection>();
1332             mock.Setup(x =>
1333                 x.GetAsync<TwitterUploadMediaResult>(
1334                     new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
1335                     new Dictionary<string, string>
1336                     {
1337                             { "command", "STATUS" },
1338                             { "media_id", "11111" },
1339                     },
1340                     null)
1341             )
1342             .ReturnsAsync(new TwitterUploadMediaResult());
1343
1344             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1345             twitterApi.ApiConnection = mock.Object;
1346
1347             await twitterApi.MediaUploadStatus(mediaId: 11111L)
1348                 .ConfigureAwait(false);
1349
1350             mock.VerifyAll();
1351         }
1352
1353         [Fact]
1354         public async Task MediaMetadataCreate_Test()
1355         {
1356             var mock = new Mock<IApiConnection>();
1357             mock.Setup(x =>
1358                 x.PostJsonAsync(
1359                     new Uri("https://upload.twitter.com/1.1/media/metadata/create.json", UriKind.Absolute),
1360                     """{"media_id": "12345", "alt_text": {"text": "hogehoge"}}""")
1361             )
1362             .Returns(Task.CompletedTask);
1363
1364             using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1365             twitterApi.ApiConnection = mock.Object;
1366
1367             await twitterApi.MediaMetadataCreate(mediaId: 12345L, altText: "hogehoge")
1368                 .ConfigureAwait(false);
1369
1370             mock.VerifyAll();
1371         }
1372     }
1373 }