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;
27 using System.Net.Http;
28 using System.Reflection;
29 using System.Runtime.InteropServices;
31 using System.Threading.Tasks;
33 using OpenTween.Api.DataModel;
34 using OpenTween.Connection;
37 namespace OpenTween.Api
39 public class TwitterApiTest
41 public TwitterApiTest()
42 => this.MyCommonSetup();
44 private void MyCommonSetup()
46 var mockAssembly = new Mock<_Assembly>();
47 mockAssembly.Setup(m => m.GetName()).Returns(new AssemblyName("OpenTween"));
49 MyCommon.EntryAssembly = mockAssembly.Object;
53 public void Initialize_Test()
55 using var twitterApi = new TwitterApi();
56 var apiConnection = Assert.IsType<TwitterApiConnection>(twitterApi.Connection);
57 Assert.IsType<TwitterCredentialNone>(apiConnection.Credential);
59 var credential = new TwitterCredentialOAuth1(TwitterAppToken.GetDefault(), "*** AccessToken ***", "*** AccessSecret ***");
60 twitterApi.Initialize(credential, userId: 100L, screenName: "hogehoge");
62 apiConnection = Assert.IsType<TwitterApiConnection>(twitterApi.Connection);
63 Assert.Same(credential, apiConnection.Credential);
65 Assert.Equal(100L, twitterApi.CurrentUserId);
66 Assert.Equal("hogehoge", twitterApi.CurrentScreenName);
68 // 複数回 Initialize を実行した場合は新たに TwitterApiConnection が生成される
69 var credential2 = new TwitterCredentialOAuth1(TwitterAppToken.GetDefault(), "*** AccessToken2 ***", "*** AccessSecret2 ***");
70 twitterApi.Initialize(credential2, userId: 200L, screenName: "foobar");
72 var oldApiConnection = apiConnection;
73 Assert.True(oldApiConnection.IsDisposed);
75 apiConnection = Assert.IsType<TwitterApiConnection>(twitterApi.Connection);
76 Assert.Same(credential2, apiConnection.Credential);
78 Assert.Equal(200L, twitterApi.CurrentUserId);
79 Assert.Equal("foobar", twitterApi.CurrentScreenName);
82 private Mock<IApiConnectionLegacy> CreateApiConnectionMock<T>(Action<T> verifyRequest)
83 where T : IHttpRequest
85 Func<T, bool> verifyRequestWrapper = r =>
88 // Assert メソッドを使用する想定のため、失敗した場合は例外が発生しここまで到達しない
92 var responseMessage = new HttpResponseMessage(HttpStatusCode.OK);
93 var mock = new Mock<IApiConnectionLegacy>();
96 It.Is<T>(r => verifyRequestWrapper(r))
99 .ReturnsAsync(new ApiResponse(responseMessage));
105 public async Task StatusesHomeTimeline_Test()
107 var mock = new Mock<IApiConnectionLegacy>();
109 x.GetAsync<TwitterStatus[]>(
110 new Uri("statuses/home_timeline.json", UriKind.Relative),
111 new Dictionary<string, string>
113 { "include_entities", "true" },
114 { "include_ext_alt_text", "true" },
115 { "tweet_mode", "extended" },
118 { "since_id", "100" },
120 "/statuses/home_timeline")
122 .ReturnsAsync(Array.Empty<TwitterStatus>());
124 using var twitterApi = new TwitterApi();
125 twitterApi.ApiConnection = mock.Object;
127 await twitterApi.StatusesHomeTimeline(200, maxId: new("900"), sinceId: new("100"));
133 public async Task StatusesMentionsTimeline_Test()
135 var mock = new Mock<IApiConnectionLegacy>();
137 x.GetAsync<TwitterStatus[]>(
138 new Uri("statuses/mentions_timeline.json", UriKind.Relative),
139 new Dictionary<string, string>
141 { "include_entities", "true" },
142 { "include_ext_alt_text", "true" },
143 { "tweet_mode", "extended" },
146 { "since_id", "100" },
148 "/statuses/mentions_timeline")
150 .ReturnsAsync(Array.Empty<TwitterStatus>());
152 using var twitterApi = new TwitterApi();
153 twitterApi.ApiConnection = mock.Object;
155 await twitterApi.StatusesMentionsTimeline(200, maxId: new("900"), sinceId: new("100"));
161 public async Task StatusesUserTimeline_Test()
163 var mock = new Mock<IApiConnectionLegacy>();
165 x.GetAsync<TwitterStatus[]>(
166 new Uri("statuses/user_timeline.json", UriKind.Relative),
167 new Dictionary<string, string>
169 { "screen_name", "twitterapi" },
170 { "include_rts", "true" },
171 { "include_entities", "true" },
172 { "include_ext_alt_text", "true" },
173 { "tweet_mode", "extended" },
176 { "since_id", "100" },
178 "/statuses/user_timeline")
180 .ReturnsAsync(Array.Empty<TwitterStatus>());
182 using var twitterApi = new TwitterApi();
183 twitterApi.ApiConnection = mock.Object;
185 await twitterApi.StatusesUserTimeline("twitterapi", count: 200, maxId: new("900"), sinceId: new("100"));
191 public async Task StatusesShow_Test()
193 var mock = new Mock<IApiConnectionLegacy>();
195 x.GetAsync<TwitterStatus>(
196 new Uri("statuses/show.json", UriKind.Relative),
197 new Dictionary<string, string>
200 { "include_entities", "true" },
201 { "include_ext_alt_text", "true" },
202 { "tweet_mode", "extended" },
204 "/statuses/show/:id")
206 .ReturnsAsync(new TwitterStatus { Id = 100L });
208 using var twitterApi = new TwitterApi();
209 twitterApi.ApiConnection = mock.Object;
211 await twitterApi.StatusesShow(statusId: new("100"));
217 public async Task StatusesLookup_Test()
219 var mock = new Mock<IApiConnectionLegacy>();
221 x.GetAsync<TwitterStatus[]>(
222 new Uri("statuses/lookup.json", UriKind.Relative),
223 new Dictionary<string, string>
226 { "include_entities", "true" },
227 { "include_ext_alt_text", "true" },
228 { "tweet_mode", "extended" },
233 .ReturnsAsync(Array.Empty<TwitterStatus>());
235 using var twitterApi = new TwitterApi();
236 twitterApi.ApiConnection = mock.Object;
238 await twitterApi.StatusesLookup(statusIds: new[] { "100", "200" });
244 public async Task StatusesUpdate_Test()
246 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
248 Assert.Equal(new("statuses/update.json", UriKind.Relative), r.RequestUri);
249 var expectedQuery = new Dictionary<string, string>
251 ["status"] = "hogehoge",
252 ["include_entities"] = "true",
253 ["include_ext_alt_text"] = "true",
254 ["tweet_mode"] = "extended",
255 ["in_reply_to_status_id"] = "100",
256 ["media_ids"] = "10,20",
257 ["auto_populate_reply_metadata"] = "true",
258 ["exclude_reply_user_ids"] = "100,200",
259 ["attachment_url"] = "https://twitter.com/twitterapi/status/22634515958",
261 Assert.Equal(expectedQuery, r.Query);
264 using var twitterApi = new TwitterApi();
265 twitterApi.ApiConnection = mock.Object;
267 await twitterApi.StatusesUpdate(
269 replyToId: new("100"),
270 mediaIds: new[] { 10L, 20L },
271 autoPopulateReplyMetadata: true,
272 excludeReplyUserIds: new[] { 100L, 200L },
273 attachmentUrl: "https://twitter.com/twitterapi/status/22634515958"
281 public async Task StatusesUpdate_ExcludeReplyUserIdsEmptyTest()
283 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
285 Assert.Equal(new("statuses/update.json", UriKind.Relative), r.RequestUri);
286 var expectedQuery = new Dictionary<string, string>
288 ["status"] = "hogehoge",
289 ["include_entities"] = "true",
290 ["include_ext_alt_text"] = "true",
291 ["tweet_mode"] = "extended",
292 // exclude_reply_user_ids は空の場合には送信されない
294 Assert.Equal(expectedQuery, r.Query);
297 using var twitterApi = new TwitterApi();
298 twitterApi.ApiConnection = mock.Object;
300 await twitterApi.StatusesUpdate("hogehoge", replyToId: null, mediaIds: null, excludeReplyUserIds: Array.Empty<long>())
307 public async Task StatusesDestroy_Test()
309 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
311 Assert.Equal(new("statuses/destroy.json", UriKind.Relative), r.RequestUri);
312 var expectedQuery = new Dictionary<string, string>
316 Assert.Equal(expectedQuery, r.Query);
319 using var twitterApi = new TwitterApi();
320 twitterApi.ApiConnection = mock.Object;
322 await twitterApi.StatusesDestroy(statusId: new("100"))
329 public async Task StatusesRetweet_Test()
331 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
333 Assert.Equal(new("statuses/retweet.json", UriKind.Relative), r.RequestUri);
334 var expectedQuery = new Dictionary<string, string>
337 ["include_entities"] = "true",
338 ["include_ext_alt_text"] = "true",
339 ["tweet_mode"] = "extended",
341 Assert.Equal(expectedQuery, r.Query);
344 using var twitterApi = new TwitterApi();
345 twitterApi.ApiConnection = mock.Object;
347 await twitterApi.StatusesRetweet(new("100"))
354 public async Task SearchTweets_Test()
356 var mock = new Mock<IApiConnectionLegacy>();
358 x.GetAsync<TwitterSearchResult>(
359 new Uri("search/tweets.json", UriKind.Relative),
360 new Dictionary<string, string>
362 { "q", "from:twitterapi" },
363 { "result_type", "recent" },
364 { "include_entities", "true" },
365 { "include_ext_alt_text", "true" },
366 { "tweet_mode", "extended" },
370 { "since_id", "100" },
374 .ReturnsAsync(new TwitterSearchResult());
376 using var twitterApi = new TwitterApi();
377 twitterApi.ApiConnection = mock.Object;
379 await twitterApi.SearchTweets("from:twitterapi", "en", count: 200, maxId: new("900"), sinceId: new("100"));
385 public async Task ListsOwnerships_Test()
387 var mock = new Mock<IApiConnectionLegacy>();
389 x.GetAsync<TwitterLists>(
390 new Uri("lists/ownerships.json", UriKind.Relative),
391 new Dictionary<string, string>
393 { "screen_name", "twitterapi" },
399 .ReturnsAsync(new TwitterLists());
401 using var twitterApi = new TwitterApi();
402 twitterApi.ApiConnection = mock.Object;
404 await twitterApi.ListsOwnerships("twitterapi", cursor: -1L, count: 100);
410 public async Task ListsSubscriptions_Test()
412 var mock = new Mock<IApiConnectionLegacy>();
414 x.GetAsync<TwitterLists>(
415 new Uri("lists/subscriptions.json", UriKind.Relative),
416 new Dictionary<string, string>
418 { "screen_name", "twitterapi" },
422 "/lists/subscriptions")
424 .ReturnsAsync(new TwitterLists());
426 using var twitterApi = new TwitterApi();
427 twitterApi.ApiConnection = mock.Object;
429 await twitterApi.ListsSubscriptions("twitterapi", cursor: -1L, count: 100);
435 public async Task ListsMemberships_Test()
437 var mock = new Mock<IApiConnectionLegacy>();
439 x.GetAsync<TwitterLists>(
440 new Uri("lists/memberships.json", UriKind.Relative),
441 new Dictionary<string, string>
443 { "screen_name", "twitterapi" },
446 { "filter_to_owned_lists", "true" },
448 "/lists/memberships")
450 .ReturnsAsync(new TwitterLists());
452 using var twitterApi = new TwitterApi();
453 twitterApi.ApiConnection = mock.Object;
455 await twitterApi.ListsMemberships("twitterapi", cursor: -1L, count: 100, filterToOwnedLists: true);
461 public async Task ListsCreate_Test()
463 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
465 Assert.Equal(new("lists/create.json", UriKind.Relative), r.RequestUri);
466 var expectedQuery = new Dictionary<string, string>
468 ["name"] = "hogehoge",
469 ["description"] = "aaaa",
470 ["mode"] = "private",
472 Assert.Equal(expectedQuery, r.Query);
475 using var twitterApi = new TwitterApi();
476 twitterApi.ApiConnection = mock.Object;
478 await twitterApi.ListsCreate("hogehoge", description: "aaaa", @private: true)
485 public async Task ListsUpdate_Test()
487 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
489 Assert.Equal(new("lists/update.json", UriKind.Relative), r.RequestUri);
490 var expectedQuery = new Dictionary<string, string>
492 ["list_id"] = "12345",
493 ["name"] = "hogehoge",
494 ["description"] = "aaaa",
495 ["mode"] = "private",
497 Assert.Equal(expectedQuery, r.Query);
500 using var twitterApi = new TwitterApi();
501 twitterApi.ApiConnection = mock.Object;
503 await twitterApi.ListsUpdate(12345L, name: "hogehoge", description: "aaaa", @private: true)
510 public async Task ListsDestroy_Test()
512 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
514 Assert.Equal(new("lists/destroy.json", UriKind.Relative), r.RequestUri);
515 var expectedQuery = new Dictionary<string, string>
517 ["list_id"] = "12345",
519 Assert.Equal(expectedQuery, r.Query);
522 using var twitterApi = new TwitterApi();
523 twitterApi.ApiConnection = mock.Object;
525 await twitterApi.ListsDestroy(12345L)
532 public async Task ListsStatuses_Test()
534 var mock = new Mock<IApiConnectionLegacy>();
536 x.GetAsync<TwitterStatus[]>(
537 new Uri("lists/statuses.json", UriKind.Relative),
538 new Dictionary<string, string>
540 { "list_id", "12345" },
541 { "include_entities", "true" },
542 { "include_ext_alt_text", "true" },
543 { "tweet_mode", "extended" },
546 { "since_id", "100" },
547 { "include_rts", "true" },
551 .ReturnsAsync(Array.Empty<TwitterStatus>());
553 using var twitterApi = new TwitterApi();
554 twitterApi.ApiConnection = mock.Object;
556 await twitterApi.ListsStatuses(12345L, count: 200, maxId: new("900"), sinceId: new("100"), includeRTs: true);
562 public async Task ListsMembers_Test()
564 var mock = new Mock<IApiConnectionLegacy>();
566 x.GetAsync<TwitterUsers>(
567 new Uri("lists/members.json", UriKind.Relative),
568 new Dictionary<string, string>
570 { "list_id", "12345" },
571 { "include_entities", "true" },
572 { "include_ext_alt_text", "true" },
573 { "tweet_mode", "extended" },
578 .ReturnsAsync(new TwitterUsers());
580 using var twitterApi = new TwitterApi();
581 twitterApi.ApiConnection = mock.Object;
583 await twitterApi.ListsMembers(12345L, cursor: -1);
589 public async Task ListsMembersShow_Test()
591 var mock = new Mock<IApiConnectionLegacy>();
593 x.GetAsync<TwitterUser>(
594 new Uri("lists/members/show.json", UriKind.Relative),
595 new Dictionary<string, string>
597 { "list_id", "12345" },
598 { "screen_name", "twitterapi" },
599 { "include_entities", "true" },
600 { "include_ext_alt_text", "true" },
601 { "tweet_mode", "extended" },
603 "/lists/members/show")
605 .ReturnsAsync(new TwitterUser());
607 using var twitterApi = new TwitterApi();
608 twitterApi.ApiConnection = mock.Object;
610 await twitterApi.ListsMembersShow(12345L, "twitterapi");
616 public async Task ListsMembersCreate_Test()
618 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
620 Assert.Equal(new("lists/members/create.json", UriKind.Relative), r.RequestUri);
621 var expectedQuery = new Dictionary<string, string>
623 ["list_id"] = "12345",
624 ["screen_name"] = "twitterapi",
625 ["include_entities"] = "true",
626 ["include_ext_alt_text"] = "true",
627 ["tweet_mode"] = "extended",
629 Assert.Equal(expectedQuery, r.Query);
632 using var twitterApi = new TwitterApi();
633 twitterApi.ApiConnection = mock.Object;
635 await twitterApi.ListsMembersCreate(12345L, "twitterapi")
642 public async Task ListsMembersDestroy_Test()
644 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
646 Assert.Equal(new("lists/members/destroy.json", UriKind.Relative), r.RequestUri);
647 var expectedQuery = new Dictionary<string, string>
649 ["list_id"] = "12345",
650 ["screen_name"] = "twitterapi",
651 ["include_entities"] = "true",
652 ["include_ext_alt_text"] = "true",
653 ["tweet_mode"] = "extended",
655 Assert.Equal(expectedQuery, r.Query);
658 using var twitterApi = new TwitterApi();
659 twitterApi.ApiConnection = mock.Object;
661 await twitterApi.ListsMembersDestroy(12345L, "twitterapi")
668 public async Task DirectMessagesEventsList_Test()
670 var mock = new Mock<IApiConnectionLegacy>();
672 x.GetAsync<TwitterMessageEventList>(
673 new Uri("direct_messages/events/list.json", UriKind.Relative),
674 new Dictionary<string, string>
677 { "cursor", "12345abcdefg" },
679 "/direct_messages/events/list")
681 .ReturnsAsync(new TwitterMessageEventList());
683 using var twitterApi = new TwitterApi();
684 twitterApi.ApiConnection = mock.Object;
686 await twitterApi.DirectMessagesEventsList(count: 50, cursor: "12345abcdefg");
692 public async Task DirectMessagesEventsNew_Test()
694 var requestJson = """
697 "type": "message_create",
700 "recipient_id": "12345"
716 var mock = this.CreateApiConnectionMock<PostJsonRequest>(r =>
718 Assert.Equal(new("direct_messages/events/new.json", UriKind.Relative), r.RequestUri);
719 Assert.Equal(requestJson, r.JsonString);
722 using var twitterApi = new TwitterApi();
723 twitterApi.ApiConnection = mock.Object;
725 await twitterApi.DirectMessagesEventsNew(recipientId: 12345L, text: "hogehoge", mediaId: 67890L);
731 public async Task DirectMessagesEventsDestroy_Test()
733 var mock = this.CreateApiConnectionMock<DeleteRequest>(r =>
735 Assert.Equal(new("direct_messages/events/destroy.json", UriKind.Relative), r.RequestUri);
736 var expectedQuery = new Dictionary<string, string>
740 Assert.Equal(expectedQuery, r.Query);
743 using var twitterApi = new TwitterApi();
744 twitterApi.ApiConnection = mock.Object;
746 await twitterApi.DirectMessagesEventsDestroy(eventId: new("100"));
752 public async Task UsersShow_Test()
754 var mock = new Mock<IApiConnectionLegacy>();
756 x.GetAsync<TwitterUser>(
757 new Uri("users/show.json", UriKind.Relative),
758 new Dictionary<string, string>
760 { "screen_name", "twitterapi" },
761 { "include_entities", "true" },
762 { "include_ext_alt_text", "true" },
763 { "tweet_mode", "extended" },
767 .ReturnsAsync(new TwitterUser { ScreenName = "twitterapi" });
769 using var twitterApi = new TwitterApi();
770 twitterApi.ApiConnection = mock.Object;
772 await twitterApi.UsersShow(screenName: "twitterapi");
778 public async Task UsersLookup_Test()
780 var mock = new Mock<IApiConnectionLegacy>();
782 x.GetAsync<TwitterUser[]>(
783 new Uri("users/lookup.json", UriKind.Relative),
784 new Dictionary<string, string>
786 { "user_id", "11111,22222" },
787 { "include_entities", "true" },
788 { "include_ext_alt_text", "true" },
789 { "tweet_mode", "extended" },
793 .ReturnsAsync(Array.Empty<TwitterUser>());
795 using var twitterApi = new TwitterApi();
796 twitterApi.ApiConnection = mock.Object;
798 await twitterApi.UsersLookup(userIds: new[] { "11111", "22222" });
804 public async Task UsersReportSpam_Test()
806 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
808 Assert.Equal(new("users/report_spam.json", UriKind.Relative), r.RequestUri);
809 var expectedQuery = new Dictionary<string, string>
811 ["screen_name"] = "twitterapi",
812 ["tweet_mode"] = "extended",
814 Assert.Equal(expectedQuery, r.Query);
817 using var twitterApi = new TwitterApi();
818 twitterApi.ApiConnection = mock.Object;
820 await twitterApi.UsersReportSpam(screenName: "twitterapi")
827 public async Task FavoritesList_Test()
829 var mock = new Mock<IApiConnectionLegacy>();
831 x.GetAsync<TwitterStatus[]>(
832 new Uri("favorites/list.json", UriKind.Relative),
833 new Dictionary<string, string>
835 { "include_entities", "true" },
836 { "include_ext_alt_text", "true" },
837 { "tweet_mode", "extended" },
840 { "since_id", "100" },
844 .ReturnsAsync(Array.Empty<TwitterStatus>());
846 using var twitterApi = new TwitterApi();
847 twitterApi.ApiConnection = mock.Object;
849 await twitterApi.FavoritesList(200, maxId: 900L, sinceId: 100L);
855 public async Task FavoritesCreate_Test()
857 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
859 Assert.Equal(new("favorites/create.json", UriKind.Relative), r.RequestUri);
860 var expectedQuery = new Dictionary<string, string>
863 ["tweet_mode"] = "extended",
865 Assert.Equal(expectedQuery, r.Query);
868 using var twitterApi = new TwitterApi();
869 twitterApi.ApiConnection = mock.Object;
871 await twitterApi.FavoritesCreate(statusId: new("100"))
878 public async Task FavoritesDestroy_Test()
880 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
882 Assert.Equal(new("favorites/destroy.json", UriKind.Relative), r.RequestUri);
883 var expectedQuery = new Dictionary<string, string>
886 ["tweet_mode"] = "extended",
888 Assert.Equal(expectedQuery, r.Query);
891 using var twitterApi = new TwitterApi();
892 twitterApi.ApiConnection = mock.Object;
894 await twitterApi.FavoritesDestroy(statusId: new("100"))
901 public async Task FriendshipsShow_Test()
903 var mock = new Mock<IApiConnectionLegacy>();
905 x.GetAsync<TwitterFriendship>(
906 new Uri("friendships/show.json", UriKind.Relative),
907 new Dictionary<string, string> { { "source_screen_name", "twitter" }, { "target_screen_name", "twitterapi" } },
910 .ReturnsAsync(new TwitterFriendship());
912 using var twitterApi = new TwitterApi();
913 twitterApi.ApiConnection = mock.Object;
915 await twitterApi.FriendshipsShow(sourceScreenName: "twitter", targetScreenName: "twitterapi");
921 public async Task FriendshipsCreate_Test()
923 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
925 Assert.Equal(new("friendships/create.json", UriKind.Relative), r.RequestUri);
926 var expectedQuery = new Dictionary<string, string>
928 ["screen_name"] = "twitterapi",
930 Assert.Equal(expectedQuery, r.Query);
933 using var twitterApi = new TwitterApi();
934 twitterApi.ApiConnection = mock.Object;
936 await twitterApi.FriendshipsCreate(screenName: "twitterapi")
943 public async Task FriendshipsDestroy_Test()
945 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
947 Assert.Equal(new("friendships/destroy.json", UriKind.Relative), r.RequestUri);
948 var expectedQuery = new Dictionary<string, string>
950 ["screen_name"] = "twitterapi",
952 Assert.Equal(expectedQuery, r.Query);
955 using var twitterApi = new TwitterApi();
956 twitterApi.ApiConnection = mock.Object;
958 await twitterApi.FriendshipsDestroy(screenName: "twitterapi")
965 public async Task NoRetweetIds_Test()
967 var mock = new Mock<IApiConnectionLegacy>();
970 new Uri("friendships/no_retweets/ids.json", UriKind.Relative),
972 "/friendships/no_retweets/ids")
974 .ReturnsAsync(Array.Empty<long>());
976 using var twitterApi = new TwitterApi();
977 twitterApi.ApiConnection = mock.Object;
979 await twitterApi.NoRetweetIds();
985 public async Task FollowersIds_Test()
987 var mock = new Mock<IApiConnectionLegacy>();
989 x.GetAsync<TwitterIds>(
990 new Uri("followers/ids.json", UriKind.Relative),
991 new Dictionary<string, string> { { "cursor", "-1" } },
994 .ReturnsAsync(new TwitterIds());
996 using var twitterApi = new TwitterApi();
997 twitterApi.ApiConnection = mock.Object;
999 await twitterApi.FollowersIds(cursor: -1L);
1005 public async Task MutesUsersIds_Test()
1007 var mock = new Mock<IApiConnectionLegacy>();
1009 x.GetAsync<TwitterIds>(
1010 new Uri("mutes/users/ids.json", UriKind.Relative),
1011 new Dictionary<string, string> { { "cursor", "-1" } },
1014 .ReturnsAsync(new TwitterIds());
1016 using var twitterApi = new TwitterApi();
1017 twitterApi.ApiConnection = mock.Object;
1019 await twitterApi.MutesUsersIds(cursor: -1L);
1025 public async Task BlocksIds_Test()
1027 var mock = new Mock<IApiConnectionLegacy>();
1029 x.GetAsync<TwitterIds>(
1030 new Uri("blocks/ids.json", UriKind.Relative),
1031 new Dictionary<string, string> { { "cursor", "-1" } },
1034 .ReturnsAsync(new TwitterIds());
1036 using var twitterApi = new TwitterApi();
1037 twitterApi.ApiConnection = mock.Object;
1039 await twitterApi.BlocksIds(cursor: -1L);
1045 public async Task BlocksCreate_Test()
1047 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
1049 Assert.Equal(new("blocks/create.json", UriKind.Relative), r.RequestUri);
1050 var expectedQuery = new Dictionary<string, string>
1052 ["screen_name"] = "twitterapi",
1053 ["tweet_mode"] = "extended",
1055 Assert.Equal(expectedQuery, r.Query);
1058 using var twitterApi = new TwitterApi();
1059 twitterApi.ApiConnection = mock.Object;
1061 await twitterApi.BlocksCreate(screenName: "twitterapi")
1068 public async Task BlocksDestroy_Test()
1070 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
1072 Assert.Equal(new("blocks/destroy.json", UriKind.Relative), r.RequestUri);
1073 var expectedQuery = new Dictionary<string, string>
1075 ["screen_name"] = "twitterapi",
1076 ["tweet_mode"] = "extended",
1078 Assert.Equal(expectedQuery, r.Query);
1081 using var twitterApi = new TwitterApi();
1082 twitterApi.ApiConnection = mock.Object;
1084 await twitterApi.BlocksDestroy(screenName: "twitterapi")
1091 public async Task AccountVerifyCredentials_Test()
1093 var mock = new Mock<IApiConnectionLegacy>();
1095 x.GetAsync<TwitterUser>(
1096 new Uri("account/verify_credentials.json", UriKind.Relative),
1097 new Dictionary<string, string>
1099 { "include_entities", "true" },
1100 { "include_ext_alt_text", "true" },
1101 { "tweet_mode", "extended" },
1103 "/account/verify_credentials")
1105 .ReturnsAsync(new TwitterUser
1108 ScreenName = "opentween",
1111 using var twitterApi = new TwitterApi();
1112 twitterApi.ApiConnection = mock.Object;
1114 await twitterApi.AccountVerifyCredentials();
1116 Assert.Equal(100L, twitterApi.CurrentUserId);
1117 Assert.Equal("opentween", twitterApi.CurrentScreenName);
1123 public async Task AccountUpdateProfile_Test()
1125 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
1127 Assert.Equal(new("account/update_profile.json", UriKind.Relative), r.RequestUri);
1128 var expectedQuery = new Dictionary<string, string>
1130 ["include_entities"] = "true",
1131 ["include_ext_alt_text"] = "true",
1132 ["tweet_mode"] = "extended",
1134 ["url"] = "http://example.com/",
1135 ["location"] = "Location",
1136 ["description"] = "<script>alert(1)</script>",
1138 Assert.Equal(expectedQuery, r.Query);
1141 using var twitterApi = new TwitterApi();
1142 twitterApi.ApiConnection = mock.Object;
1144 await twitterApi.AccountUpdateProfile(name: "Name", url: "http://example.com/", location: "Location", description: "<script>alert(1)</script>")
1151 public async Task AccountUpdateProfileImage_Test()
1153 using var image = TestUtils.CreateDummyImage();
1154 using var media = new MemoryImageMediaItem(image);
1156 var mock = this.CreateApiConnectionMock<PostMultipartRequest>(r =>
1158 Assert.Equal(new("account/update_profile_image.json", UriKind.Relative), r.RequestUri);
1159 var expectedQuery = new Dictionary<string, string>
1161 ["include_entities"] = "true",
1162 ["include_ext_alt_text"] = "true",
1163 ["tweet_mode"] = "extended",
1165 Assert.Equal(expectedQuery, r.Query);
1166 var expectedMedia = new Dictionary<string, IMediaItem>
1170 Assert.Equal(expectedMedia, r.Media);
1173 using var twitterApi = new TwitterApi();
1174 twitterApi.ApiConnection = mock.Object;
1176 await twitterApi.AccountUpdateProfileImage(media)
1183 public async Task ApplicationRateLimitStatus_Test()
1185 var mock = new Mock<IApiConnectionLegacy>();
1187 x.GetAsync<TwitterRateLimits>(
1188 new Uri("application/rate_limit_status.json", UriKind.Relative),
1190 "/application/rate_limit_status")
1192 .ReturnsAsync(new TwitterRateLimits());
1194 using var twitterApi = new TwitterApi();
1195 twitterApi.ApiConnection = mock.Object;
1197 await twitterApi.ApplicationRateLimitStatus();
1203 public async Task Configuration_Test()
1205 var mock = new Mock<IApiConnectionLegacy>();
1207 x.GetAsync<TwitterConfiguration>(
1208 new Uri("help/configuration.json", UriKind.Relative),
1210 "/help/configuration")
1212 .ReturnsAsync(new TwitterConfiguration());
1214 using var twitterApi = new TwitterApi();
1215 twitterApi.ApiConnection = mock.Object;
1217 await twitterApi.Configuration();
1223 public async Task MediaUploadInit_Test()
1225 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
1227 Assert.Equal(new("https://upload.twitter.com/1.1/media/upload.json"), r.RequestUri);
1228 var expectedQuery = new Dictionary<string, string>
1230 ["command"] = "INIT",
1231 ["total_bytes"] = "123456",
1232 ["media_type"] = "image/png",
1233 ["media_category"] = "dm_image",
1235 Assert.Equal(expectedQuery, r.Query);
1238 using var twitterApi = new TwitterApi();
1239 twitterApi.ApiConnection = mock.Object;
1241 await twitterApi.MediaUploadInit(totalBytes: 123456L, mediaType: "image/png", mediaCategory: "dm_image")
1248 public async Task MediaUploadAppend_Test()
1250 using var image = TestUtils.CreateDummyImage();
1251 using var media = new MemoryImageMediaItem(image);
1253 var mock = this.CreateApiConnectionMock<PostMultipartRequest>(r =>
1255 Assert.Equal(new("https://upload.twitter.com/1.1/media/upload.json"), r.RequestUri);
1256 var expectedQuery = new Dictionary<string, string>
1258 ["command"] = "APPEND",
1259 ["media_id"] = "11111",
1260 ["segment_index"] = "1",
1262 Assert.Equal(expectedQuery, r.Query);
1263 var expectedMedia = new Dictionary<string, IMediaItem>
1267 Assert.Equal(expectedMedia, r.Media);
1270 using var twitterApi = new TwitterApi();
1271 twitterApi.ApiConnection = mock.Object;
1273 await twitterApi.MediaUploadAppend(mediaId: 11111L, segmentIndex: 1, media: media);
1279 public async Task MediaUploadFinalize_Test()
1281 var mock = this.CreateApiConnectionMock<PostRequest>(r =>
1283 Assert.Equal(new("https://upload.twitter.com/1.1/media/upload.json"), r.RequestUri);
1284 var expectedQuery = new Dictionary<string, string>
1286 ["command"] = "FINALIZE",
1287 ["media_id"] = "11111",
1289 Assert.Equal(expectedQuery, r.Query);
1292 using var twitterApi = new TwitterApi();
1293 twitterApi.ApiConnection = mock.Object;
1295 await twitterApi.MediaUploadFinalize(mediaId: 11111L)
1302 public async Task MediaUploadStatus_Test()
1304 var mock = new Mock<IApiConnectionLegacy>();
1306 x.GetAsync<TwitterUploadMediaResult>(
1307 new Uri("https://upload.twitter.com/1.1/media/upload.json", UriKind.Absolute),
1308 new Dictionary<string, string>
1310 { "command", "STATUS" },
1311 { "media_id", "11111" },
1315 .ReturnsAsync(new TwitterUploadMediaResult());
1317 using var twitterApi = new TwitterApi();
1318 twitterApi.ApiConnection = mock.Object;
1320 await twitterApi.MediaUploadStatus(mediaId: 11111L);
1326 public async Task MediaMetadataCreate_Test()
1328 var mock = this.CreateApiConnectionMock<PostJsonRequest>(r =>
1330 Assert.Equal(new("https://upload.twitter.com/1.1/media/metadata/create.json"), r.RequestUri);
1331 Assert.Equal("""{"media_id": "12345", "alt_text": {"text": "hogehoge"}}""", r.JsonString);
1334 using var twitterApi = new TwitterApi();
1335 twitterApi.ApiConnection = mock.Object;
1337 await twitterApi.MediaMetadataCreate(mediaId: 12345L, altText: "hogehoge");