OSDN Git Service

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