1 // OpenTween - Client of Twitter
2 // Copyright (c) 2016 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
5 // This file is part of OpenTween.
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)
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
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.
23 using System.Collections.Generic;
26 using System.Net.Http;
27 using System.Reflection;
28 using System.Runtime.InteropServices;
30 using System.Threading.Tasks;
32 using OpenTween.Api.DataModel;
33 using OpenTween.Connection;
36 namespace OpenTween.Api
38 public class TwitterApiTest
40 public TwitterApiTest()
41 => this.MyCommonSetup();
43 private void MyCommonSetup()
45 var mockAssembly = new Mock<_Assembly>();
46 mockAssembly.Setup(m => m.GetName()).Returns(new AssemblyName("OpenTween"));
48 MyCommon.EntryAssembly = mockAssembly.Object;
52 public void Initialize_Test()
54 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
55 Assert.Null(twitterApi.ApiConnection);
57 twitterApi.Initialize("*** AccessToken ***", "*** AccessSecret ***", userId: 100L, screenName: "hogehoge");
59 Assert.IsType<TwitterApiConnection>(twitterApi.ApiConnection);
61 var apiConnection = (TwitterApiConnection)twitterApi.ApiConnection!;
62 Assert.Equal("*** AccessToken ***", apiConnection.AccessToken);
63 Assert.Equal("*** AccessSecret ***", apiConnection.AccessSecret);
65 Assert.Equal(100L, twitterApi.CurrentUserId);
66 Assert.Equal("hogehoge", twitterApi.CurrentScreenName);
68 // 複数回 Initialize を実行した場合は新たに TwitterApiConnection が生成される
69 twitterApi.Initialize("*** AccessToken2 ***", "*** AccessSecret2 ***", userId: 200L, screenName: "foobar");
71 var oldApiConnection = apiConnection;
72 Assert.True(oldApiConnection.IsDisposed);
74 Assert.IsType<TwitterApiConnection>(twitterApi.ApiConnection);
76 apiConnection = (TwitterApiConnection)twitterApi.ApiConnection!;
77 Assert.Equal("*** AccessToken2 ***", apiConnection.AccessToken);
78 Assert.Equal("*** AccessSecret2 ***", apiConnection.AccessSecret);
80 Assert.Equal(200L, twitterApi.CurrentUserId);
81 Assert.Equal("foobar", twitterApi.CurrentScreenName);
85 public async Task StatusesHomeTimeline_Test()
87 var mock = new Mock<IApiConnection>();
89 x.GetAsync<TwitterStatus[]>(
90 new Uri("statuses/home_timeline.json", UriKind.Relative),
91 new Dictionary<string, string>
93 { "include_entities", "true" },
94 { "include_ext_alt_text", "true" },
95 { "tweet_mode", "extended" },
98 { "since_id", "100" },
100 "/statuses/home_timeline")
102 .ReturnsAsync(Array.Empty<TwitterStatus>());
104 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
105 twitterApi.ApiConnection = mock.Object;
107 await twitterApi.StatusesHomeTimeline(200, maxId: 900L, sinceId: 100L)
108 .ConfigureAwait(false);
114 public async Task StatusesMentionsTimeline_Test()
116 var mock = new Mock<IApiConnection>();
118 x.GetAsync<TwitterStatus[]>(
119 new Uri("statuses/mentions_timeline.json", UriKind.Relative),
120 new Dictionary<string, string>
122 { "include_entities", "true" },
123 { "include_ext_alt_text", "true" },
124 { "tweet_mode", "extended" },
127 { "since_id", "100" },
129 "/statuses/mentions_timeline")
131 .ReturnsAsync(Array.Empty<TwitterStatus>());
133 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
134 twitterApi.ApiConnection = mock.Object;
136 await twitterApi.StatusesMentionsTimeline(200, maxId: 900L, sinceId: 100L)
137 .ConfigureAwait(false);
143 public async Task StatusesUserTimeline_Test()
145 var mock = new Mock<IApiConnection>();
147 x.GetAsync<TwitterStatus[]>(
148 new Uri("statuses/user_timeline.json", UriKind.Relative),
149 new Dictionary<string, string>
151 { "screen_name", "twitterapi" },
152 { "include_rts", "true" },
153 { "include_entities", "true" },
154 { "include_ext_alt_text", "true" },
155 { "tweet_mode", "extended" },
158 { "since_id", "100" },
160 "/statuses/user_timeline")
162 .ReturnsAsync(Array.Empty<TwitterStatus>());
164 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
165 twitterApi.ApiConnection = mock.Object;
167 await twitterApi.StatusesUserTimeline("twitterapi", count: 200, maxId: 900L, sinceId: 100L)
168 .ConfigureAwait(false);
174 public async Task StatusesShow_Test()
176 var mock = new Mock<IApiConnection>();
178 x.GetAsync<TwitterStatus>(
179 new Uri("statuses/show.json", UriKind.Relative),
180 new Dictionary<string, string>
183 { "include_entities", "true" },
184 { "include_ext_alt_text", "true" },
185 { "tweet_mode", "extended" },
187 "/statuses/show/:id")
189 .ReturnsAsync(new TwitterStatus { Id = 100L });
191 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
192 twitterApi.ApiConnection = mock.Object;
194 await twitterApi.StatusesShow(statusId: 100L)
195 .ConfigureAwait(false);
201 public async Task StatusesUpdate_Test()
203 var mock = new Mock<IApiConnection>();
205 x.PostLazyAsync<TwitterStatus>(
206 new Uri("statuses/update.json", UriKind.Relative),
207 new Dictionary<string, string>
209 { "status", "hogehoge" },
210 { "include_entities", "true" },
211 { "include_ext_alt_text", "true" },
212 { "tweet_mode", "extended" },
213 { "in_reply_to_status_id", "100" },
214 { "media_ids", "10,20" },
215 { "auto_populate_reply_metadata", "true" },
216 { "exclude_reply_user_ids", "100,200" },
217 { "attachment_url", "https://twitter.com/twitterapi/status/22634515958" },
220 .ReturnsAsync(LazyJson.Create(new TwitterStatus()));
222 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
223 twitterApi.ApiConnection = mock.Object;
225 await twitterApi.StatusesUpdate(
228 mediaIds: new[] { 10L, 20L },
229 autoPopulateReplyMetadata: true,
230 excludeReplyUserIds: new[] { 100L, 200L },
231 attachmentUrl: "https://twitter.com/twitterapi/status/22634515958"
234 .ConfigureAwait(false);
240 public async Task StatusesUpdate_ExcludeReplyUserIdsEmptyTest()
242 var mock = new Mock<IApiConnection>();
244 x.PostLazyAsync<TwitterStatus>(
245 new Uri("statuses/update.json", UriKind.Relative),
246 new Dictionary<string, string>
248 { "status", "hogehoge" },
249 { "include_entities", "true" },
250 { "include_ext_alt_text", "true" },
251 { "tweet_mode", "extended" },
252 // exclude_reply_user_ids は空の場合には送信されない
255 .ReturnsAsync(LazyJson.Create(new TwitterStatus()));
257 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
258 twitterApi.ApiConnection = mock.Object;
260 await twitterApi.StatusesUpdate("hogehoge", replyToId: null, mediaIds: null, excludeReplyUserIds: Array.Empty<long>())
262 .ConfigureAwait(false);
268 public async Task StatusesDestroy_Test()
270 var mock = new Mock<IApiConnection>();
272 x.PostLazyAsync<TwitterStatus>(
273 new Uri("statuses/destroy.json", UriKind.Relative),
274 new Dictionary<string, string> { { "id", "100" } })
276 .ReturnsAsync(LazyJson.Create(new TwitterStatus { Id = 100L }));
278 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
279 twitterApi.ApiConnection = mock.Object;
281 await twitterApi.StatusesDestroy(statusId: 100L)
283 .ConfigureAwait(false);
289 public async Task StatusesRetweet_Test()
291 var mock = new Mock<IApiConnection>();
293 x.PostLazyAsync<TwitterStatus>(
294 new Uri("statuses/retweet.json", UriKind.Relative),
295 new Dictionary<string, string>
298 { "include_entities", "true" },
299 { "include_ext_alt_text", "true" },
300 { "tweet_mode", "extended" },
303 .ReturnsAsync(LazyJson.Create(new TwitterStatus()));
305 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
306 twitterApi.ApiConnection = mock.Object;
308 await twitterApi.StatusesRetweet(100L)
310 .ConfigureAwait(false);
316 public async Task SearchTweets_Test()
318 var mock = new Mock<IApiConnection>();
320 x.GetAsync<TwitterSearchResult>(
321 new Uri("search/tweets.json", UriKind.Relative),
322 new Dictionary<string, string>
324 { "q", "from:twitterapi" },
325 { "result_type", "recent" },
326 { "include_entities", "true" },
327 { "include_ext_alt_text", "true" },
328 { "tweet_mode", "extended" },
332 { "since_id", "100" },
336 .ReturnsAsync(new TwitterSearchResult());
338 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
339 twitterApi.ApiConnection = mock.Object;
341 await twitterApi.SearchTweets("from:twitterapi", "en", count: 200, maxId: 900L, sinceId: 100L)
342 .ConfigureAwait(false);
348 public async Task ListsOwnerships_Test()
350 var mock = new Mock<IApiConnection>();
352 x.GetAsync<TwitterLists>(
353 new Uri("lists/ownerships.json", UriKind.Relative),
354 new Dictionary<string, string>
356 { "screen_name", "twitterapi" },
362 .ReturnsAsync(new TwitterLists());
364 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
365 twitterApi.ApiConnection = mock.Object;
367 await twitterApi.ListsOwnerships("twitterapi", cursor: -1L, count: 100)
368 .ConfigureAwait(false);
374 public async Task ListsSubscriptions_Test()
376 var mock = new Mock<IApiConnection>();
378 x.GetAsync<TwitterLists>(
379 new Uri("lists/subscriptions.json", UriKind.Relative),
380 new Dictionary<string, string>
382 { "screen_name", "twitterapi" },
386 "/lists/subscriptions")
388 .ReturnsAsync(new TwitterLists());
390 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
391 twitterApi.ApiConnection = mock.Object;
393 await twitterApi.ListsSubscriptions("twitterapi", cursor: -1L, count: 100)
394 .ConfigureAwait(false);
400 public async Task ListsMemberships_Test()
402 var mock = new Mock<IApiConnection>();
404 x.GetAsync<TwitterLists>(
405 new Uri("lists/memberships.json", UriKind.Relative),
406 new Dictionary<string, string>
408 { "screen_name", "twitterapi" },
411 { "filter_to_owned_lists", "true" },
413 "/lists/memberships")
415 .ReturnsAsync(new TwitterLists());
417 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
418 twitterApi.ApiConnection = mock.Object;
420 await twitterApi.ListsMemberships("twitterapi", cursor: -1L, count: 100, filterToOwnedLists: true)
421 .ConfigureAwait(false);
427 public async Task ListsCreate_Test()
429 var mock = new Mock<IApiConnection>();
431 x.PostLazyAsync<TwitterList>(
432 new Uri("lists/create.json", UriKind.Relative),
433 new Dictionary<string, string>
435 { "name", "hogehoge" },
436 { "description", "aaaa" },
437 { "mode", "private" },
440 .ReturnsAsync(LazyJson.Create(new TwitterList()));
442 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
443 twitterApi.ApiConnection = mock.Object;
445 await twitterApi.ListsCreate("hogehoge", description: "aaaa", @private: true)
447 .ConfigureAwait(false);
453 public async Task ListsUpdate_Test()
455 var mock = new Mock<IApiConnection>();
457 x.PostLazyAsync<TwitterList>(
458 new Uri("lists/update.json", UriKind.Relative),
459 new Dictionary<string, string>
461 { "list_id", "12345" },
462 { "name", "hogehoge" },
463 { "description", "aaaa" },
464 { "mode", "private" },
467 .ReturnsAsync(LazyJson.Create(new TwitterList()));
469 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
470 twitterApi.ApiConnection = mock.Object;
472 await twitterApi.ListsUpdate(12345L, name: "hogehoge", description: "aaaa", @private: true)
474 .ConfigureAwait(false);
480 public async Task ListsDestroy_Test()
482 var mock = new Mock<IApiConnection>();
484 x.PostLazyAsync<TwitterList>(
485 new Uri("lists/destroy.json", UriKind.Relative),
486 new Dictionary<string, string>
488 { "list_id", "12345" },
491 .ReturnsAsync(LazyJson.Create(new TwitterList()));
493 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
494 twitterApi.ApiConnection = mock.Object;
496 await twitterApi.ListsDestroy(12345L)
498 .ConfigureAwait(false);
504 public async Task ListsStatuses_Test()
506 var mock = new Mock<IApiConnection>();
508 x.GetAsync<TwitterStatus[]>(
509 new Uri("lists/statuses.json", UriKind.Relative),
510 new Dictionary<string, string>
512 { "list_id", "12345" },
513 { "include_entities", "true" },
514 { "include_ext_alt_text", "true" },
515 { "tweet_mode", "extended" },
518 { "since_id", "100" },
519 { "include_rts", "true" },
523 .ReturnsAsync(Array.Empty<TwitterStatus>());
525 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
526 twitterApi.ApiConnection = mock.Object;
528 await twitterApi.ListsStatuses(12345L, count: 200, maxId: 900L, sinceId: 100L, includeRTs: true)
529 .ConfigureAwait(false);
535 public async Task ListsMembers_Test()
537 var mock = new Mock<IApiConnection>();
539 x.GetAsync<TwitterUsers>(
540 new Uri("lists/members.json", UriKind.Relative),
541 new Dictionary<string, string>
543 { "list_id", "12345" },
544 { "include_entities", "true" },
545 { "include_ext_alt_text", "true" },
546 { "tweet_mode", "extended" },
551 .ReturnsAsync(new TwitterUsers());
553 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
554 twitterApi.ApiConnection = mock.Object;
556 await twitterApi.ListsMembers(12345L, cursor: -1)
557 .ConfigureAwait(false);
563 public async Task ListsMembersShow_Test()
565 var mock = new Mock<IApiConnection>();
567 x.GetAsync<TwitterUser>(
568 new Uri("lists/members/show.json", UriKind.Relative),
569 new Dictionary<string, string>
571 { "list_id", "12345" },
572 { "screen_name", "twitterapi" },
573 { "include_entities", "true" },
574 { "include_ext_alt_text", "true" },
575 { "tweet_mode", "extended" },
577 "/lists/members/show")
579 .ReturnsAsync(new TwitterUser());
581 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
582 twitterApi.ApiConnection = mock.Object;
584 await twitterApi.ListsMembersShow(12345L, "twitterapi")
585 .ConfigureAwait(false);
591 public async Task ListsMembersCreate_Test()
593 var mock = new Mock<IApiConnection>();
595 x.PostLazyAsync<TwitterUser>(
596 new Uri("lists/members/create.json", UriKind.Relative),
597 new Dictionary<string, string>
599 { "list_id", "12345" },
600 { "screen_name", "twitterapi" },
601 { "include_entities", "true" },
602 { "include_ext_alt_text", "true" },
603 { "tweet_mode", "extended" },
606 .ReturnsAsync(LazyJson.Create(new TwitterUser()));
608 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
609 twitterApi.ApiConnection = mock.Object;
611 await twitterApi.ListsMembersCreate(12345L, "twitterapi")
613 .ConfigureAwait(false);
619 public async Task ListsMembersDestroy_Test()
621 var mock = new Mock<IApiConnection>();
623 x.PostLazyAsync<TwitterUser>(
624 new Uri("lists/members/destroy.json", UriKind.Relative),
625 new Dictionary<string, string>
627 { "list_id", "12345" },
628 { "screen_name", "twitterapi" },
629 { "include_entities", "true" },
630 { "include_ext_alt_text", "true" },
631 { "tweet_mode", "extended" },
634 .ReturnsAsync(LazyJson.Create(new TwitterUser()));
636 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
637 twitterApi.ApiConnection = mock.Object;
639 await twitterApi.ListsMembersDestroy(12345L, "twitterapi")
641 .ConfigureAwait(false);
647 public async Task DirectMessagesEventsList_Test()
649 var mock = new Mock<IApiConnection>();
651 x.GetAsync<TwitterMessageEventList>(
652 new Uri("direct_messages/events/list.json", UriKind.Relative),
653 new Dictionary<string, string>
656 { "cursor", "12345abcdefg" },
658 "/direct_messages/events/list")
660 .ReturnsAsync(new TwitterMessageEventList());
662 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
663 twitterApi.ApiConnection = mock.Object;
665 await twitterApi.DirectMessagesEventsList(count: 50, cursor: "12345abcdefg")
666 .ConfigureAwait(false);
672 public async Task DirectMessagesEventsNew_Test()
674 var mock = new Mock<IApiConnection>();
675 var responseText = @"{
677 ""type"": ""message_create"",
678 ""message_create"": {
680 ""recipient_id"": ""12345""
683 ""text"": ""hogehoge"",
695 x.PostJsonAsync<TwitterMessageEventSingle>(
696 new Uri("direct_messages/events/new.json", UriKind.Relative),
699 .ReturnsAsync(LazyJson.Create(new TwitterMessageEventSingle()));
701 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
702 twitterApi.ApiConnection = mock.Object;
704 await twitterApi.DirectMessagesEventsNew(recipientId: 12345L, text: "hogehoge", mediaId: 67890L)
705 .ConfigureAwait(false);
711 public async Task DirectMessagesEventsDestroy_Test()
713 var mock = new Mock<IApiConnection>();
716 new Uri("direct_messages/events/destroy.json?id=100", UriKind.Relative))
718 .Returns(Task.CompletedTask);
720 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
721 twitterApi.ApiConnection = mock.Object;
723 await twitterApi.DirectMessagesEventsDestroy(eventId: "100")
724 .ConfigureAwait(false);
730 public async Task UsersShow_Test()
732 var mock = new Mock<IApiConnection>();
734 x.GetAsync<TwitterUser>(
735 new Uri("users/show.json", UriKind.Relative),
736 new Dictionary<string, string>
738 { "screen_name", "twitterapi" },
739 { "include_entities", "true" },
740 { "include_ext_alt_text", "true" },
741 { "tweet_mode", "extended" },
745 .ReturnsAsync(new TwitterUser { ScreenName = "twitterapi" });
747 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
748 twitterApi.ApiConnection = mock.Object;
750 await twitterApi.UsersShow(screenName: "twitterapi")
751 .ConfigureAwait(false);
757 public async Task UsersLookup_Test()
759 var mock = new Mock<IApiConnection>();
761 x.GetAsync<TwitterUser[]>(
762 new Uri("users/lookup.json", UriKind.Relative),
763 new Dictionary<string, string>
765 { "user_id", "11111,22222" },
766 { "include_entities", "true" },
767 { "include_ext_alt_text", "true" },
768 { "tweet_mode", "extended" },
772 .ReturnsAsync(Array.Empty<TwitterUser>());
774 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
775 twitterApi.ApiConnection = mock.Object;
777 await twitterApi.UsersLookup(userIds: new[] { "11111", "22222" })
778 .ConfigureAwait(false);
784 public async Task UsersReportSpam_Test()
786 var mock = new Mock<IApiConnection>();
788 x.PostLazyAsync<TwitterUser>(
789 new Uri("users/report_spam.json", UriKind.Relative),
790 new Dictionary<string, string>
792 { "screen_name", "twitterapi" },
793 { "tweet_mode", "extended" },
796 .ReturnsAsync(LazyJson.Create(new TwitterUser { ScreenName = "twitterapi" }));
798 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
799 twitterApi.ApiConnection = mock.Object;
801 await twitterApi.UsersReportSpam(screenName: "twitterapi")
803 .ConfigureAwait(false);
809 public async Task FavoritesList_Test()
811 var mock = new Mock<IApiConnection>();
813 x.GetAsync<TwitterStatus[]>(
814 new Uri("favorites/list.json", UriKind.Relative),
815 new Dictionary<string, string>
817 { "include_entities", "true" },
818 { "include_ext_alt_text", "true" },
819 { "tweet_mode", "extended" },
822 { "since_id", "100" },
826 .ReturnsAsync(Array.Empty<TwitterStatus>());
828 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
829 twitterApi.ApiConnection = mock.Object;
831 await twitterApi.FavoritesList(200, maxId: 900L, sinceId: 100L)
832 .ConfigureAwait(false);
838 public async Task FavoritesCreate_Test()
840 var mock = new Mock<IApiConnection>();
842 x.PostLazyAsync<TwitterStatus>(
843 new Uri("favorites/create.json", UriKind.Relative),
844 new Dictionary<string, string>
847 { "tweet_mode", "extended" },
850 .ReturnsAsync(LazyJson.Create(new TwitterStatus { Id = 100L }));
852 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
853 twitterApi.ApiConnection = mock.Object;
855 await twitterApi.FavoritesCreate(statusId: 100L)
857 .ConfigureAwait(false);
863 public async Task FavoritesDestroy_Test()
865 var mock = new Mock<IApiConnection>();
867 x.PostLazyAsync<TwitterStatus>(
868 new Uri("favorites/destroy.json", UriKind.Relative),
869 new Dictionary<string, string>
872 { "tweet_mode", "extended" },
875 .ReturnsAsync(LazyJson.Create(new TwitterStatus { Id = 100L }));
877 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
878 twitterApi.ApiConnection = mock.Object;
880 await twitterApi.FavoritesDestroy(statusId: 100L)
882 .ConfigureAwait(false);
888 public async Task FriendshipsShow_Test()
890 var mock = new Mock<IApiConnection>();
892 x.GetAsync<TwitterFriendship>(
893 new Uri("friendships/show.json", UriKind.Relative),
894 new Dictionary<string, string> { { "source_screen_name", "twitter" }, { "target_screen_name", "twitterapi" } },
897 .ReturnsAsync(new TwitterFriendship());
899 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
900 twitterApi.ApiConnection = mock.Object;
902 await twitterApi.FriendshipsShow(sourceScreenName: "twitter", targetScreenName: "twitterapi")
903 .ConfigureAwait(false);
909 public async Task FriendshipsCreate_Test()
911 var mock = new Mock<IApiConnection>();
913 x.PostLazyAsync<TwitterFriendship>(
914 new Uri("friendships/create.json", UriKind.Relative),
915 new Dictionary<string, string> { { "screen_name", "twitterapi" } })
917 .ReturnsAsync(LazyJson.Create(new TwitterFriendship()));
919 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
920 twitterApi.ApiConnection = mock.Object;
922 await twitterApi.FriendshipsCreate(screenName: "twitterapi")
924 .ConfigureAwait(false);
930 public async Task FriendshipsDestroy_Test()
932 var mock = new Mock<IApiConnection>();
934 x.PostLazyAsync<TwitterFriendship>(
935 new Uri("friendships/destroy.json", UriKind.Relative),
936 new Dictionary<string, string> { { "screen_name", "twitterapi" } })
938 .ReturnsAsync(LazyJson.Create(new TwitterFriendship()));
940 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
941 twitterApi.ApiConnection = mock.Object;
943 await twitterApi.FriendshipsDestroy(screenName: "twitterapi")
945 .ConfigureAwait(false);
951 public async Task NoRetweetIds_Test()
953 var mock = new Mock<IApiConnection>();
956 new Uri("friendships/no_retweets/ids.json", UriKind.Relative),
958 "/friendships/no_retweets/ids")
960 .ReturnsAsync(Array.Empty<long>());
962 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
963 twitterApi.ApiConnection = mock.Object;
965 await twitterApi.NoRetweetIds()
966 .ConfigureAwait(false);
972 public async Task FollowersIds_Test()
974 var mock = new Mock<IApiConnection>();
976 x.GetAsync<TwitterIds>(
977 new Uri("followers/ids.json", UriKind.Relative),
978 new Dictionary<string, string> { { "cursor", "-1" } },
981 .ReturnsAsync(new TwitterIds());
983 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
984 twitterApi.ApiConnection = mock.Object;
986 await twitterApi.FollowersIds(cursor: -1L)
987 .ConfigureAwait(false);
993 public async Task MutesUsersIds_Test()
995 var mock = new Mock<IApiConnection>();
997 x.GetAsync<TwitterIds>(
998 new Uri("mutes/users/ids.json", UriKind.Relative),
999 new Dictionary<string, string> { { "cursor", "-1" } },
1002 .ReturnsAsync(new TwitterIds());
1004 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1005 twitterApi.ApiConnection = mock.Object;
1007 await twitterApi.MutesUsersIds(cursor: -1L)
1008 .ConfigureAwait(false);
1014 public async Task BlocksIds_Test()
1016 var mock = new Mock<IApiConnection>();
1018 x.GetAsync<TwitterIds>(
1019 new Uri("blocks/ids.json", UriKind.Relative),
1020 new Dictionary<string, string> { { "cursor", "-1" } },
1023 .ReturnsAsync(new TwitterIds());
1025 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1026 twitterApi.ApiConnection = mock.Object;
1028 await twitterApi.BlocksIds(cursor: -1L)
1029 .ConfigureAwait(false);
1035 public async Task BlocksCreate_Test()
1037 var mock = new Mock<IApiConnection>();
1039 x.PostLazyAsync<TwitterUser>(
1040 new Uri("blocks/create.json", UriKind.Relative),
1041 new Dictionary<string, string>
1043 { "screen_name", "twitterapi" },
1044 { "tweet_mode", "extended" },
1047 .ReturnsAsync(LazyJson.Create(new TwitterUser()));
1049 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1050 twitterApi.ApiConnection = mock.Object;
1052 await twitterApi.BlocksCreate(screenName: "twitterapi")
1054 .ConfigureAwait(false);
1060 public async Task BlocksDestroy_Test()
1062 var mock = new Mock<IApiConnection>();
1064 x.PostLazyAsync<TwitterUser>(
1065 new Uri("blocks/destroy.json", UriKind.Relative),
1066 new Dictionary<string, string>
1068 { "screen_name", "twitterapi" },
1069 { "tweet_mode", "extended" },
1072 .ReturnsAsync(LazyJson.Create(new TwitterUser()));
1074 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1075 twitterApi.ApiConnection = mock.Object;
1077 await twitterApi.BlocksDestroy(screenName: "twitterapi")
1079 .ConfigureAwait(false);
1085 public async Task AccountVerifyCredentials_Test()
1087 var mock = new Mock<IApiConnection>();
1089 x.GetAsync<TwitterUser>(
1090 new Uri("account/verify_credentials.json", UriKind.Relative),
1091 new Dictionary<string, string>
1093 { "include_entities", "true" },
1094 { "include_ext_alt_text", "true" },
1095 { "tweet_mode", "extended" },
1097 "/account/verify_credentials")
1099 .ReturnsAsync(new TwitterUser
1102 ScreenName = "opentween",
1105 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1106 twitterApi.ApiConnection = mock.Object;
1108 await twitterApi.AccountVerifyCredentials()
1109 .ConfigureAwait(false);
1111 Assert.Equal(100L, twitterApi.CurrentUserId);
1112 Assert.Equal("opentween", twitterApi.CurrentScreenName);
1118 public async Task AccountUpdateProfile_Test()
1120 var mock = new Mock<IApiConnection>();
1122 x.PostLazyAsync<TwitterUser>(
1123 new Uri("account/update_profile.json", UriKind.Relative),
1124 new Dictionary<string, string>
1126 { "include_entities", "true" },
1127 { "include_ext_alt_text", "true" },
1128 { "tweet_mode", "extended" },
1130 { "url", "http://example.com/" },
1131 { "location", "Location" },
1132 { "description", "<script>alert(1)</script>" },
1135 .ReturnsAsync(LazyJson.Create(new TwitterUser()));
1137 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1138 twitterApi.ApiConnection = mock.Object;
1140 await twitterApi.AccountUpdateProfile(name: "Name", url: "http://example.com/", location: "Location", description: "<script>alert(1)</script>")
1142 .ConfigureAwait(false);
1148 public async Task AccountUpdateProfileImage_Test()
1150 using var image = TestUtils.CreateDummyImage();
1151 using var media = new MemoryImageMediaItem(image);
1152 var mock = new Mock<IApiConnection>();
1154 x.PostLazyAsync<TwitterUser>(
1155 new Uri("account/update_profile_image.json", UriKind.Relative),
1156 new Dictionary<string, string>
1158 { "include_entities", "true" },
1159 { "include_ext_alt_text", "true" },
1160 { "tweet_mode", "extended" },
1162 new Dictionary<string, IMediaItem> { { "image", media } })
1164 .ReturnsAsync(LazyJson.Create(new TwitterUser()));
1166 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1167 twitterApi.ApiConnection = mock.Object;
1169 await twitterApi.AccountUpdateProfileImage(media)
1171 .ConfigureAwait(false);
1177 public async Task ApplicationRateLimitStatus_Test()
1179 var mock = new Mock<IApiConnection>();
1181 x.GetAsync<TwitterRateLimits>(
1182 new Uri("application/rate_limit_status.json", UriKind.Relative),
1184 "/application/rate_limit_status")
1186 .ReturnsAsync(new TwitterRateLimits());
1188 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1189 twitterApi.ApiConnection = mock.Object;
1191 await twitterApi.ApplicationRateLimitStatus()
1192 .ConfigureAwait(false);
1198 public async Task Configuration_Test()
1200 var mock = new Mock<IApiConnection>();
1202 x.GetAsync<TwitterConfiguration>(
1203 new Uri("help/configuration.json", UriKind.Relative),
1205 "/help/configuration")
1207 .ReturnsAsync(new TwitterConfiguration());
1209 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1210 twitterApi.ApiConnection = mock.Object;
1212 await twitterApi.Configuration()
1213 .ConfigureAwait(false);
1219 public async Task MediaUploadInit_Test()
1221 var mock = new Mock<IApiConnection>();
1223 x.PostLazyAsync<TwitterUploadMediaInit>(
1224 new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
1225 new Dictionary<string, string>
1227 { "command", "INIT" },
1228 { "total_bytes", "123456" },
1229 { "media_type", "image/png" },
1230 { "media_category", "dm_image" },
1233 .ReturnsAsync(LazyJson.Create(new TwitterUploadMediaInit()));
1235 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1236 twitterApi.ApiConnection = mock.Object;
1238 await twitterApi.MediaUploadInit(totalBytes: 123456L, mediaType: "image/png", mediaCategory: "dm_image")
1240 .ConfigureAwait(false);
1246 public async Task MediaUploadAppend_Test()
1248 using var image = TestUtils.CreateDummyImage();
1249 using var media = new MemoryImageMediaItem(image);
1250 var mock = new Mock<IApiConnection>();
1253 new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
1254 new Dictionary<string, string>
1256 { "command", "APPEND" },
1257 { "media_id", "11111" },
1258 { "segment_index", "1" },
1260 new Dictionary<string, IMediaItem> { { "media", media } })
1262 .Returns(Task.CompletedTask);
1264 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1265 twitterApi.ApiConnection = mock.Object;
1267 await twitterApi.MediaUploadAppend(mediaId: 11111L, segmentIndex: 1, media: media)
1268 .ConfigureAwait(false);
1274 public async Task MediaUploadFinalize_Test()
1276 var mock = new Mock<IApiConnection>();
1278 x.PostLazyAsync<TwitterUploadMediaResult>(
1279 new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
1280 new Dictionary<string, string>
1282 { "command", "FINALIZE" },
1283 { "media_id", "11111" },
1286 .ReturnsAsync(LazyJson.Create(new TwitterUploadMediaResult()));
1288 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1289 twitterApi.ApiConnection = mock.Object;
1291 await twitterApi.MediaUploadFinalize(mediaId: 11111L)
1293 .ConfigureAwait(false);
1299 public async Task MediaUploadStatus_Test()
1301 var mock = new Mock<IApiConnection>();
1303 x.GetAsync<TwitterUploadMediaResult>(
1304 new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
1305 new Dictionary<string, string>
1307 { "command", "STATUS" },
1308 { "media_id", "11111" },
1312 .ReturnsAsync(new TwitterUploadMediaResult());
1314 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1315 twitterApi.ApiConnection = mock.Object;
1317 await twitterApi.MediaUploadStatus(mediaId: 11111L)
1318 .ConfigureAwait(false);
1324 public async Task MediaMetadataCreate_Test()
1326 var mock = new Mock<IApiConnection>();
1329 new Uri("https://upload.twitter.com/1.1/media/metadata/create.json", UriKind.Absolute),
1330 "{\"media_id\": \"12345\", \"alt_text\": {\"text\": \"hogehoge\"}}")
1332 .Returns(Task.CompletedTask);
1334 using var twitterApi = new TwitterApi(ApiKey.Create("fake_consumer_key"), ApiKey.Create("fake_consumer_secret"));
1335 twitterApi.ApiConnection = mock.Object;
1337 await twitterApi.MediaMetadataCreate(mediaId: 12345L, altText: "hogehoge")
1338 .ConfigureAwait(false);