Skip to content

Commit

Permalink
Merge pull request #274 from opentween/api-connection
Browse files Browse the repository at this point in the history
PostJsonRequestクラスを追加
  • Loading branch information
upsilon authored Dec 10, 2023
2 parents c05ddf7 + b7475a7 commit d44e636
Show file tree
Hide file tree
Showing 16 changed files with 304 additions and 152 deletions.
20 changes: 8 additions & 12 deletions OpenTween.Tests/Api/GraphQL/CreateRetweetRequestTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@
// 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.Text;
using System.Threading.Tasks;
using Moq;
using OpenTween.Connection;
Expand All @@ -36,18 +31,19 @@ public class CreateRetweetRequestTest
[Fact]
public async Task Send_Test()
{
var responseText = File.ReadAllText("Resources/Responses/CreateRetweet.json");
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/CreateRetweet.json");

var mock = new Mock<IApiConnectionLegacy>();
var mock = new Mock<IApiConnection>();
mock.Setup(x =>
x.PostJsonAsync(It.IsAny<Uri>(), It.IsAny<string>())
x.SendAsync(It.IsAny<IHttpRequest>())
)
.Callback<Uri, string>((url, json) =>
.Callback<IHttpRequest>(x =>
{
Assert.Equal(new("https://twitter.com/i/api/graphql/ojPdsZsimiJrUGLR1sjUtA/CreateRetweet"), url);
Assert.Contains(@"""tweet_id"":""12345""", json);
var request = Assert.IsType<PostJsonRequest>(x);
Assert.Equal(new("https://twitter.com/i/api/graphql/ojPdsZsimiJrUGLR1sjUtA/CreateRetweet"), request.RequestUri);
Assert.Contains(@"""tweet_id"":""12345""", request.JsonString);
})
.ReturnsAsync(responseText);
.ReturnsAsync(apiResponse);

var request = new CreateRetweetRequest
{
Expand Down
50 changes: 24 additions & 26 deletions OpenTween.Tests/Api/GraphQL/CreateTweetRequestTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@
// 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.Text;
using System.Threading.Tasks;
using Moq;
using OpenTween.Connection;
Expand All @@ -36,20 +31,21 @@ public class CreateTweetRequestTest
[Fact]
public async Task Send_Test()
{
var responseText = File.ReadAllText("Resources/Responses/CreateTweet_CircleTweet.json");
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/CreateTweet_CircleTweet.json");

var mock = new Mock<IApiConnectionLegacy>();
var mock = new Mock<IApiConnection>();
mock.Setup(x =>
x.PostJsonAsync(It.IsAny<Uri>(), It.IsAny<string>())
x.SendAsync(It.IsAny<IHttpRequest>())
)
.Callback<Uri, string>((url, json) =>
.Callback<IHttpRequest>(x =>
{
Assert.Equal(new("https://twitter.com/i/api/graphql/tTsjMKyhajZvK4q76mpIBg/CreateTweet"), url);
Assert.Contains(@"""tweet_text"":""tetete""", json);
Assert.DoesNotContain(@"""reply"":", json);
Assert.DoesNotContain(@"""media"":", json);
var request = Assert.IsType<PostJsonRequest>(x);
Assert.Equal(new("https://twitter.com/i/api/graphql/tTsjMKyhajZvK4q76mpIBg/CreateTweet"), request.RequestUri);
Assert.Contains(@"""tweet_text"":""tetete""", request.JsonString);
Assert.DoesNotContain(@"""reply"":", request.JsonString);
Assert.DoesNotContain(@"""media"":", request.JsonString);
})
.ReturnsAsync(responseText);
.ReturnsAsync(apiResponse);

var request = new CreateTweetRequest
{
Expand All @@ -65,17 +61,18 @@ public async Task Send_Test()
[Fact]
public async Task Send_ReplyTest()
{
var responseText = File.ReadAllText("Resources/Responses/CreateTweet_CircleTweet.json");
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/CreateTweet_CircleTweet.json");

var mock = new Mock<IApiConnectionLegacy>();
var mock = new Mock<IApiConnection>();
mock.Setup(x =>
x.PostJsonAsync(It.IsAny<Uri>(), It.IsAny<string>())
x.SendAsync(It.IsAny<IHttpRequest>())
)
.Callback<Uri, string>((url, json) =>
.Callback<IHttpRequest>(x =>
{
Assert.Contains(@"""reply"":{""exclude_reply_user_ids"":[""11111"",""22222""],""in_reply_to_tweet_id"":""12345""}", json);
var request = Assert.IsType<PostJsonRequest>(x);
Assert.Contains(@"""reply"":{""exclude_reply_user_ids"":[""11111"",""22222""],""in_reply_to_tweet_id"":""12345""}", request.JsonString);
})
.ReturnsAsync(responseText);
.ReturnsAsync(apiResponse);

var request = new CreateTweetRequest
{
Expand All @@ -90,17 +87,18 @@ public async Task Send_ReplyTest()
[Fact]
public async Task Send_MediaTest()
{
var responseText = File.ReadAllText("Resources/Responses/CreateTweet_CircleTweet.json");
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/CreateTweet_CircleTweet.json");

var mock = new Mock<IApiConnectionLegacy>();
var mock = new Mock<IApiConnection>();
mock.Setup(x =>
x.PostJsonAsync(It.IsAny<Uri>(), It.IsAny<string>())
x.SendAsync(It.IsAny<IHttpRequest>())
)
.Callback<Uri, string>((url, json) =>
.Callback<IHttpRequest>(x =>
{
Assert.Contains(@"""media"":{""media_entities"":[{""media_id"":""11111"",""tagged_users"":[]},{""media_id"":""22222"",""tagged_users"":[]}],""possibly_sensitive"":false}", json);
var request = Assert.IsType<PostJsonRequest>(x);
Assert.Contains(@"""media"":{""media_entities"":[{""media_id"":""11111"",""tagged_users"":[]},{""media_id"":""22222"",""tagged_users"":[]}],""possibly_sensitive"":false}", request.JsonString);
})
.ReturnsAsync(responseText);
.ReturnsAsync(apiResponse);

var request = new CreateTweetRequest
{
Expand Down
21 changes: 10 additions & 11 deletions OpenTween.Tests/Api/GraphQL/DeleteRetweetRequestTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@
// 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.Text;
using System.Threading.Tasks;
using Moq;
using OpenTween.Connection;
Expand All @@ -36,15 +31,19 @@ public class DeleteRetweetRequestTest
[Fact]
public async Task Send_Test()
{
var mock = new Mock<IApiConnectionLegacy>();
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/DeleteRetweet.json");

var mock = new Mock<IApiConnection>();
mock.Setup(x =>
x.PostJsonAsync(It.IsAny<Uri>(), It.IsAny<string>())
x.SendAsync(It.IsAny<IHttpRequest>())
)
.Callback<Uri, string>((url, json) =>
.Callback<IHttpRequest>(x =>
{
Assert.Equal(new("https://twitter.com/i/api/graphql/iQtK4dl5hBmXewYZuEOKVw/DeleteRetweet"), url);
Assert.Contains(@"""source_tweet_id"":""12345""", json);
});
var request = Assert.IsType<PostJsonRequest>(x);
Assert.Equal(new("https://twitter.com/i/api/graphql/iQtK4dl5hBmXewYZuEOKVw/DeleteRetweet"), request.RequestUri);
Assert.Contains(@"""source_tweet_id"":""12345""", request.JsonString);
})
.ReturnsAsync(apiResponse);

var request = new DeleteRetweetRequest
{
Expand Down
21 changes: 10 additions & 11 deletions OpenTween.Tests/Api/GraphQL/DeleteTweetRequestTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@
// 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.Text;
using System.Threading.Tasks;
using Moq;
using OpenTween.Connection;
Expand All @@ -36,15 +31,19 @@ public class DeleteTweetRequestTest
[Fact]
public async Task Send_Test()
{
var mock = new Mock<IApiConnectionLegacy>();
using var apiResponse = await TestUtils.CreateApiResponse("Resources/Responses/DeleteTweet.json");

var mock = new Mock<IApiConnection>();
mock.Setup(x =>
x.PostJsonAsync(It.IsAny<Uri>(), It.IsAny<string>())
x.SendAsync(It.IsAny<IHttpRequest>())
)
.Callback<Uri, string>((url, json) =>
.Callback<IHttpRequest>(x =>
{
Assert.Equal(new("https://twitter.com/i/api/graphql/VaenaVgh5q5ih7kvyVjgtg/DeleteTweet"), url);
Assert.Contains(@"""tweet_id"":""12345""", json);
});
var request = Assert.IsType<PostJsonRequest>(x);
Assert.Equal(new("https://twitter.com/i/api/graphql/VaenaVgh5q5ih7kvyVjgtg/DeleteTweet"), request.RequestUri);
Assert.Contains(@"""tweet_id"":""12345""", request.JsonString);
})
.ReturnsAsync(apiResponse);

var request = new DeleteTweetRequest
{
Expand Down
45 changes: 45 additions & 0 deletions OpenTween.Tests/Connection/ApiResponseTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,50 @@ public async Task ReadAsJsonXml_InvalidJsonTest()
);
Assert.Equal("### Invalid JSON Response ###", ex.ResponseText);
}

[Fact]
public async Task ReadAsLazyJson_Test()
{
using var responseContent = new StringContent("""{"foo":123}""");
using var responseMessage = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = responseContent,
};
using var response = new ApiResponse(responseMessage);

using var lazyJson = response.ReadAsLazyJson<TestJson>();
Assert.Equal(new() { Foo = 123 }, await lazyJson.LoadJsonAsync());
}

[Fact]
public async Task ReadAsLazyJson_DisposeTest()
{
using var responseContent = new StringContent("""{"foo":123}""");
using var responseMessage = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = responseContent,
};
using var response = new ApiResponse(responseMessage);
using var lazyJson = response.ReadAsLazyJson<TestJson>();
response.Dispose(); // ApiResponse を先に破棄しても LazyJson に影響しないことをテストする

Assert.Equal(new() { Foo = 123 }, await lazyJson.LoadJsonAsync());
}

[Fact]
public async Task ReadAsString_Test()
{
using var responseContent = new StringContent("foo");
using var responseMessage = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = responseContent,
};
using var response = new ApiResponse(responseMessage);

Assert.Equal("foo", await response.ReadAsString());
}
}
}
48 changes: 48 additions & 0 deletions OpenTween.Tests/Connection/PostJsonRequestTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// OpenTween - Client of Twitter
// Copyright (c) 2023 kim_upsilon (@kim_upsilon) <https://upsilo.net/~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 <http://www.gnu.org/licenses/>, or write to
// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
// Boston, MA 02110-1301, USA.

using System;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

namespace OpenTween.Connection
{
public class PostJsonRequestTest
{
[Fact]
public async Task CreateMessage_Test()
{
var request = new PostJsonRequest
{
RequestUri = new("aaa/bbb.json", UriKind.Relative),
JsonString = """{"foo":12345}""",
};

var baseUri = new Uri("https://example.com/v1/");
using var requestMessage = request.CreateMessage(baseUri);

Assert.Equal(HttpMethod.Post, requestMessage.Method);
Assert.Equal(new("https://example.com/v1/aaa/bbb.json"), requestMessage.RequestUri);
Assert.Equal("""{"foo":12345}""", await requestMessage.Content.ReadAsStringAsync());
}
}
}
6 changes: 6 additions & 0 deletions OpenTween.Tests/OpenTween.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@
<None Update="Resources\Responses\CreateTweet_CircleTweet.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\Responses\DeleteRetweet.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\Responses\DeleteTweet.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\Responses\Error_NotFound.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
14 changes: 14 additions & 0 deletions OpenTween.Tests/Resources/Responses/DeleteRetweet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"data": {
"unretweet": {
"source_tweet_results": {
"result": {
"rest_id": "1234567890123456789",
"legacy": {
"full_text": "foo"
}
}
}
}
}
}
7 changes: 7 additions & 0 deletions OpenTween.Tests/Resources/Responses/DeleteTweet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"data": {
"delete_tweet": {
"tweet_results": {}
}
}
}
25 changes: 12 additions & 13 deletions OpenTween/Api/GraphQL/CreateRetweetRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,7 @@
#nullable enable

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using OpenTween.Connection;
using OpenTween.Models;
Expand All @@ -49,14 +42,20 @@ public string CreateRequestBody()
""";
}

public async Task<TwitterStatusId> Send(IApiConnectionLegacy apiConnection)
public async Task<TwitterStatusId> Send(IApiConnection apiConnection)
{
var json = this.CreateRequestBody();
var response = await apiConnection.PostJsonAsync(EndpointUri, json);
var responseBytes = Encoding.UTF8.GetBytes(response);
using var jsonReader = JsonReaderWriterFactory.CreateJsonReader(responseBytes, XmlDictionaryReaderQuotas.Max);
var request = new PostJsonRequest
{
RequestUri = EndpointUri,
JsonString = this.CreateRequestBody(),
};

using var response = await apiConnection.SendAsync(request)
.ConfigureAwait(false);

var rootElm = await response.ReadAsJsonXml()
.ConfigureAwait(false);

var rootElm = XElement.Load(jsonReader);
ErrorResponse.ThrowIfError(rootElm);

var tweetIdStr = rootElm.XPathSelectElement("/data/create_retweet/retweet_results/result/rest_id")?.Value ?? throw CreateParseError();
Expand Down
Loading

0 comments on commit d44e636

Please sign in to comment.