OSDN Git Service

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