// OpenTween - Client of Twitter // Copyright (c) 2016 kim_upsilon (@kim_upsilon) // All rights reserved. // // This file is part of OpenTween. // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 3 of the License, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with this program. If not, see , or write to // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, // Boston, MA 02110-1301, USA. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Moq; using OpenTween.Api.DataModel; using OpenTween.Connection; using Xunit; namespace OpenTween.Api { public class TwitterApiTest { public TwitterApiTest() => this.MyCommonSetup(); private void MyCommonSetup() { var mockAssembly = new Mock<_Assembly>(); mockAssembly.Setup(m => m.GetName()).Returns(new AssemblyName("OpenTween")); MyCommon.EntryAssembly = mockAssembly.Object; } [Fact] public void Initialize_Test() { using var twitterApi = new TwitterApi(); var apiConnection = Assert.IsType(twitterApi.Connection); Assert.IsType(apiConnection.Credential); var credential = new TwitterCredentialOAuth1(TwitterAppToken.GetDefault(), "*** AccessToken ***", "*** AccessSecret ***"); twitterApi.Initialize(credential, userId: 100L, screenName: "hogehoge"); apiConnection = Assert.IsType(twitterApi.Connection); Assert.Same(credential, apiConnection.Credential); Assert.Equal(100L, twitterApi.CurrentUserId); Assert.Equal("hogehoge", twitterApi.CurrentScreenName); // 複数回 Initialize を実行した場合は新たに TwitterApiConnection が生成される var credential2 = new TwitterCredentialOAuth1(TwitterAppToken.GetDefault(), "*** AccessToken2 ***", "*** AccessSecret2 ***"); twitterApi.Initialize(credential2, userId: 200L, screenName: "foobar"); var oldApiConnection = apiConnection; Assert.True(oldApiConnection.IsDisposed); apiConnection = Assert.IsType(twitterApi.Connection); Assert.Same(credential2, apiConnection.Credential); Assert.Equal(200L, twitterApi.CurrentUserId); Assert.Equal("foobar", twitterApi.CurrentScreenName); } private Mock CreateApiConnectionMock(Action verifyRequest) where T : IHttpRequest => this.CreateApiConnectionMock(verifyRequest, ""); private Mock CreateApiConnectionMock(Action verifyRequest, string responseText) where T : IHttpRequest { Func verifyRequestWrapper = r => { verifyRequest(r); // Assert メソッドを使用する想定のため、失敗した場合は例外が発生しここまで到達しない return true; }; var responseMessage = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(responseText), }; var mock = new Mock(); mock.Setup(x => x.SendAsync( It.Is(r => verifyRequestWrapper(r)) ) ) .ReturnsAsync(new ApiResponse(responseMessage)); return mock; } [Fact] public async Task StatusesHomeTimeline_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("statuses/home_timeline.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", ["count"] = "200", ["max_id"] = "900", ["since_id"] = "100", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/statuses/home_timeline", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(Array.Empty()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.StatusesHomeTimeline(200, maxId: new("900"), sinceId: new("100")); mock.VerifyAll(); } [Fact] public async Task StatusesMentionsTimeline_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("statuses/mentions_timeline.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", ["count"] = "200", ["max_id"] = "900", ["since_id"] = "100", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/statuses/mentions_timeline", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(Array.Empty()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.StatusesMentionsTimeline(200, maxId: new("900"), sinceId: new("100")); mock.VerifyAll(); } [Fact] public async Task StatusesUserTimeline_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("statuses/user_timeline.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["screen_name"] = "twitterapi", ["include_rts"] = "true", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", ["count"] = "200", ["max_id"] = "900", ["since_id"] = "100", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/statuses/user_timeline", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(Array.Empty()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.StatusesUserTimeline("twitterapi", count: 200, maxId: new("900"), sinceId: new("100")); mock.VerifyAll(); } [Fact] public async Task StatusesShow_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("statuses/show.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["id"] = "100", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/statuses/show/:id", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterStatus()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.StatusesShow(statusId: new("100")); mock.VerifyAll(); } [Fact] public async Task StatusesLookup_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("statuses/lookup.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["id"] = "100,200", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/statuses/lookup", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(Array.Empty()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.StatusesLookup(statusIds: new[] { "100", "200" }); mock.VerifyAll(); } [Fact] public async Task StatusesUpdate_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("statuses/update.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["status"] = "hogehoge", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", ["in_reply_to_status_id"] = "100", ["media_ids"] = "10,20", ["auto_populate_reply_metadata"] = "true", ["exclude_reply_user_ids"] = "100,200", ["attachment_url"] = "https://twitter.com/twitterapi/status/22634515958", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.StatusesUpdate( "hogehoge", replyToId: new("100"), mediaIds: new[] { 10L, 20L }, autoPopulateReplyMetadata: true, excludeReplyUserIds: new[] { 100L, 200L }, attachmentUrl: "https://twitter.com/twitterapi/status/22634515958" ) .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task StatusesUpdate_ExcludeReplyUserIdsEmptyTest() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("statuses/update.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["status"] = "hogehoge", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", // exclude_reply_user_ids は空の場合には送信されない }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.StatusesUpdate("hogehoge", replyToId: null, mediaIds: null, excludeReplyUserIds: Array.Empty()) .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task StatusesDestroy_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("statuses/destroy.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["id"] = "100", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.StatusesDestroy(statusId: new("100")) .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task StatusesRetweet_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("statuses/retweet.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["id"] = "100", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.StatusesRetweet(new("100")) .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task SearchTweets_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("search/tweets.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["q"] = "from:twitterapi", ["result_type"] = "recent", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", ["lang"] = "en", ["count"] = "200", ["max_id"] = "900", ["since_id"] = "100", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/search/tweets", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterSearchResult()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.SearchTweets("from:twitterapi", "en", count: 200, maxId: new("900"), sinceId: new("100")); mock.VerifyAll(); } [Fact] public async Task ListsOwnerships_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("lists/ownerships.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["screen_name"] = "twitterapi", ["cursor"] = "-1", ["count"] = "100", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/lists/ownerships", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterLists()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.ListsOwnerships("twitterapi", cursor: -1L, count: 100); mock.VerifyAll(); } [Fact] public async Task ListsSubscriptions_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("lists/subscriptions.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["screen_name"] = "twitterapi", ["cursor"] = "-1", ["count"] = "100", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/lists/subscriptions", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterLists()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.ListsSubscriptions("twitterapi", cursor: -1L, count: 100); mock.VerifyAll(); } [Fact] public async Task ListsMemberships_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("lists/memberships.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["screen_name"] = "twitterapi", ["cursor"] = "-1", ["count"] = "100", ["filter_to_owned_lists"] = "true", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/lists/memberships", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterLists()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.ListsMemberships("twitterapi", cursor: -1L, count: 100, filterToOwnedLists: true); mock.VerifyAll(); } [Fact] public async Task ListsCreate_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("lists/create.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["name"] = "hogehoge", ["description"] = "aaaa", ["mode"] = "private", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.ListsCreate("hogehoge", description: "aaaa", @private: true) .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task ListsUpdate_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("lists/update.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["list_id"] = "12345", ["name"] = "hogehoge", ["description"] = "aaaa", ["mode"] = "private", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.ListsUpdate(12345L, name: "hogehoge", description: "aaaa", @private: true) .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task ListsDestroy_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("lists/destroy.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["list_id"] = "12345", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.ListsDestroy(12345L) .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task ListsStatuses_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("lists/statuses.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["list_id"] = "12345", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", ["count"] = "200", ["max_id"] = "900", ["since_id"] = "100", ["include_rts"] = "true", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/lists/statuses", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(Array.Empty()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.ListsStatuses(12345L, count: 200, maxId: new("900"), sinceId: new("100"), includeRTs: true); mock.VerifyAll(); } [Fact] public async Task ListsMembers_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("lists/members.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["list_id"] = "12345", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", ["cursor"] = "-1", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/lists/members", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(Array.Empty()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.ListsMembers(12345L, cursor: -1); mock.VerifyAll(); } [Fact] public async Task ListsMembersShow_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("lists/members/show.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["list_id"] = "12345", ["screen_name"] = "twitterapi", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/lists/members/show", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterUser()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.ListsMembersShow(12345L, "twitterapi"); mock.VerifyAll(); } [Fact] public async Task ListsMembersCreate_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("lists/members/create.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["list_id"] = "12345", ["screen_name"] = "twitterapi", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.ListsMembersCreate(12345L, "twitterapi") .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task ListsMembersDestroy_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("lists/members/destroy.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["list_id"] = "12345", ["screen_name"] = "twitterapi", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.ListsMembersDestroy(12345L, "twitterapi") .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task DirectMessagesEventsList_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("direct_messages/events/list.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["count"] = "50", ["cursor"] = "12345abcdefg", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/direct_messages/events/list", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterMessageEventList()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.DirectMessagesEventsList(count: 50, cursor: "12345abcdefg"); mock.VerifyAll(); } [Fact] public async Task DirectMessagesEventsNew_Test() { var requestJson = """ { "event": { "type": "message_create", "message_create": { "target": { "recipient_id": "12345" }, "message_data": { "text": "hogehoge", "attachment": { "type": "media", "media": { "id": "67890" } } } } } } """; var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("direct_messages/events/new.json", UriKind.Relative), r.RequestUri); Assert.Equal(requestJson, r.JsonString); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.DirectMessagesEventsNew(recipientId: 12345L, text: "hogehoge", mediaId: 67890L); mock.VerifyAll(); } [Fact] public async Task DirectMessagesEventsDestroy_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("direct_messages/events/destroy.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["id"] = "100", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.DirectMessagesEventsDestroy(eventId: new("100")); mock.VerifyAll(); } [Fact] public async Task UsersShow_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("users/show.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["screen_name"] = "twitterapi", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/users/show/:id", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterUser()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.UsersShow(screenName: "twitterapi"); mock.VerifyAll(); } [Fact] public async Task UsersLookup_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("users/lookup.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["user_id"] = "11111,22222", ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/users/lookup", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(Array.Empty()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.UsersLookup(userIds: new[] { "11111", "22222" }); mock.VerifyAll(); } [Fact] public async Task UsersReportSpam_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("users/report_spam.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["screen_name"] = "twitterapi", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.UsersReportSpam(screenName: "twitterapi") .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task FavoritesList_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("favorites/list.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", ["count"] = "200", ["max_id"] = "900", ["since_id"] = "100", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/favorites/list", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterStatus()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.FavoritesList(200, maxId: 900L, sinceId: 100L); mock.VerifyAll(); } [Fact] public async Task FavoritesCreate_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("favorites/create.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["id"] = "100", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.FavoritesCreate(statusId: new("100")) .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task FavoritesDestroy_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("favorites/destroy.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["id"] = "100", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.FavoritesDestroy(statusId: new("100")) .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task FriendshipsShow_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("friendships/show.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["source_screen_name"] = "twitter", ["target_screen_name"] = "twitterapi", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/friendships/show", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterFriendship()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.FriendshipsShow(sourceScreenName: "twitter", targetScreenName: "twitterapi"); mock.VerifyAll(); } [Fact] public async Task FriendshipsCreate_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("friendships/create.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["screen_name"] = "twitterapi", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.FriendshipsCreate(screenName: "twitterapi") .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task FriendshipsDestroy_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("friendships/destroy.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["screen_name"] = "twitterapi", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.FriendshipsDestroy(screenName: "twitterapi") .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task NoRetweetIds_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("friendships/no_retweets/ids.json", UriKind.Relative), r.RequestUri); Assert.Null(r.Query); Assert.Equal("/friendships/no_retweets/ids", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(Array.Empty()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.NoRetweetIds(); mock.VerifyAll(); } [Fact] public async Task FollowersIds_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("followers/ids.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["cursor"] = "-1", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/followers/ids", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterIds()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.FollowersIds(cursor: -1L); mock.VerifyAll(); } [Fact] public async Task MutesUsersIds_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("mutes/users/ids.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["cursor"] = "-1", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/mutes/users/ids", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterIds()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.MutesUsersIds(cursor: -1L); mock.VerifyAll(); } [Fact] public async Task BlocksIds_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("blocks/ids.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["cursor"] = "-1", }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/blocks/ids", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterIds()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.BlocksIds(cursor: -1L); mock.VerifyAll(); } [Fact] public async Task BlocksCreate_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("blocks/create.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["screen_name"] = "twitterapi", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.BlocksCreate(screenName: "twitterapi") .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task BlocksDestroy_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("blocks/destroy.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["screen_name"] = "twitterapi", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.BlocksDestroy(screenName: "twitterapi") .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task AccountVerifyCredentials_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("account/verify_credentials.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { { "include_entities", "true" }, { "include_ext_alt_text", "true" }, { "tweet_mode", "extended" }, }; Assert.Equal(expectedQuery, r.Query); Assert.Equal("/account/verify_credentials", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterUser { Id = 100L, ScreenName = "opentween", }) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.AccountVerifyCredentials(); Assert.Equal(100L, twitterApi.CurrentUserId); Assert.Equal("opentween", twitterApi.CurrentScreenName); mock.VerifyAll(); } [Fact] public async Task AccountUpdateProfile_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("account/update_profile.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", ["name"] = "Name", ["url"] = "http://example.com/", ["location"] = "Location", ["description"] = "<script>alert(1)</script>", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.AccountUpdateProfile(name: "Name", url: "http://example.com/", location: "Location", description: "") .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task AccountUpdateProfileImage_Test() { using var image = TestUtils.CreateDummyImage(); using var media = new MemoryImageMediaItem(image); var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("account/update_profile_image.json", UriKind.Relative), r.RequestUri); var expectedQuery = new Dictionary { ["include_entities"] = "true", ["include_ext_alt_text"] = "true", ["tweet_mode"] = "extended", }; Assert.Equal(expectedQuery, r.Query); var expectedMedia = new Dictionary { ["image"] = media, }; Assert.Equal(expectedMedia, r.Media); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.AccountUpdateProfileImage(media) .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task ApplicationRateLimitStatus_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("application/rate_limit_status.json", UriKind.Relative), r.RequestUri); Assert.Null(r.Query); Assert.Equal("/application/rate_limit_status", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterRateLimits()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.ApplicationRateLimitStatus(); mock.VerifyAll(); } [Fact] public async Task Configuration_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("help/configuration.json", UriKind.Relative), r.RequestUri); Assert.Null(r.Query); Assert.Equal("/help/configuration", r.EndpointName); }, JsonUtils.SerializeJsonByDataContract(new TwitterConfiguration()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.Configuration(); mock.VerifyAll(); } [Fact] public async Task MediaUploadInit_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("https://upload.twitter.com/1.1/media/upload.json"), r.RequestUri); var expectedQuery = new Dictionary { ["command"] = "INIT", ["total_bytes"] = "123456", ["media_type"] = "image/png", ["media_category"] = "dm_image", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.MediaUploadInit(totalBytes: 123456L, mediaType: "image/png", mediaCategory: "dm_image") .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task MediaUploadAppend_Test() { using var image = TestUtils.CreateDummyImage(); using var media = new MemoryImageMediaItem(image); var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("https://upload.twitter.com/1.1/media/upload.json"), r.RequestUri); var expectedQuery = new Dictionary { ["command"] = "APPEND", ["media_id"] = "11111", ["segment_index"] = "1", }; Assert.Equal(expectedQuery, r.Query); var expectedMedia = new Dictionary { ["media"] = media, }; Assert.Equal(expectedMedia, r.Media); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.MediaUploadAppend(mediaId: 11111L, segmentIndex: 1, media: media); mock.VerifyAll(); } [Fact] public async Task MediaUploadFinalize_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("https://upload.twitter.com/1.1/media/upload.json"), r.RequestUri); var expectedQuery = new Dictionary { ["command"] = "FINALIZE", ["media_id"] = "11111", }; Assert.Equal(expectedQuery, r.Query); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.MediaUploadFinalize(mediaId: 11111L) .IgnoreResponse(); mock.VerifyAll(); } [Fact] public async Task MediaUploadStatus_Test() { var mock = this.CreateApiConnectionMock( r => { Assert.Equal(new("https://upload.twitter.com/1.1/media/upload.json"), r.RequestUri); var expectedQuery = new Dictionary { ["command"] = "STATUS", ["media_id"] = "11111", }; Assert.Equal(expectedQuery, r.Query); }, JsonUtils.SerializeJsonByDataContract(new TwitterUploadMediaResult()) ); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.MediaUploadStatus(mediaId: 11111L); mock.VerifyAll(); } [Fact] public async Task MediaMetadataCreate_Test() { var mock = this.CreateApiConnectionMock(r => { Assert.Equal(new("https://upload.twitter.com/1.1/media/metadata/create.json"), r.RequestUri); Assert.Equal("""{"media_id": "12345", "alt_text": {"text": "hogehoge"}}""", r.JsonString); }); using var twitterApi = new TwitterApi(); twitterApi.ApiConnection = mock.Object; await twitterApi.MediaMetadataCreate(mediaId: 12345L, altText: "hogehoge"); mock.VerifyAll(); } } }