Skip to content
Merged

v109 #1963

Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactoring tests
  • Loading branch information
alexeyzimarev committed Nov 21, 2022
commit 19c30a81cfbf8499d20f33a9700956c1bb38d235
6 changes: 6 additions & 0 deletions src/RestSharp/IRestClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@
namespace RestSharp;

public interface IRestClient : IDisposable {
/// <summary>
/// Client options that aren't used for configuring HttpClient
/// </summary>
IRestClientOptions Options { get; }

/// <summary>
/// Client-level serializers
/// </summary>
RestSerializers Serializers { get; }

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/RestSharp/Request/RestRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using System.Net;
using RestSharp.Extensions;

// ReSharper disable ReplaceSubstringWithRangeIndexer
// ReSharper disable UnusedAutoPropertyAccessor.Global

namespace RestSharp;
Expand Down
19 changes: 10 additions & 9 deletions src/RestSharp/Request/UriExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,21 @@ params ParametersCollection[] parametersCollections
if (parameters.Count == 0) return mergedUri;

var uri = mergedUri.AbsoluteUri;
var separator = uri.Contains("?") ? "&" : "?";
var separator = uri.Contains('?') ? "&" : "?";

return new Uri(string.Concat(uri, separator, EncodeParameters()));

string EncodeParameters() => string.Join("&", parameters.Select(EncodeParameter).ToArray());

string EncodeParameter(Parameter parameter) {
return
!parameter.Encode
? $"{parameter.Name}={StringOrEmpty(parameter.Value)}"
: $"{encodeQuery(parameter.Name!, encoding)}={encodeQuery(StringOrEmpty(parameter.Value), encoding)}";

static string StringOrEmpty(object? value) => value == null ? "" : value.ToString()!;
string GetString(string name, string? value, Func<string, string>? encode) {
var val = encode != null && value != null ? encode(value) : value;
return val == null ? name : $"{name}={val}";
}

string EncodeParameter(Parameter parameter)
=> !parameter.Encode
? GetString(parameter.Name!, parameter.Value?.ToString(), null)
: GetString(encodeQuery(parameter.Name!, encoding), parameter.Value?.ToString(), x => encodeQuery(x, encoding));
}

public static UrlSegmentParamsValues GetUrlSegmentParamsValues(
Expand Down Expand Up @@ -91,4 +92,4 @@ params ParametersCollection[] parametersCollections
}
}

record UrlSegmentParamsValues(Uri Uri, string Resource);
record UrlSegmentParamsValues(Uri Uri, string Resource);
46 changes: 38 additions & 8 deletions src/RestSharp/RestClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,24 @@ public partial class RestClient : IRestClient {

HttpClient HttpClient { get; }

public IRestClientOptions Options { get; }
public RestSerializers Serializers { get; }
/// <inheritdoc />>
public IRestClientOptions Options { get; }

/// <inheritdoc />>
public RestSerializers Serializers { get; }

[Obsolete("Use RestClientOptions.Authenticator instead")]
public IAuthenticator? Authenticator {
get => Options.Authenticator;
set => Options.Authenticator = value;
}

/// <summary>
/// Creates an instance of RestClient using the provided <see cref="RestClientOptions"/>
/// </summary>
/// <param name="options">Client options</param>
/// <param name="configureDefaultHeaders">Delegate to add default headers to the wrapped HttpClient instance</param>
/// <param name="configureSerialization">Delegate to configure serialization</param>
public RestClient(
RestClientOptions options,
ConfigureHeaders? configureDefaultHeaders = null,
Expand Down Expand Up @@ -77,28 +86,49 @@ static RestClientOptions ConfigureOptions(RestClientOptions options, ConfigureRe
/// Creates an instance of RestClient using the default <see cref="RestClientOptions"/>
/// </summary>
/// <param name="configureRestClient">Delegate to configure the client options</param>
/// <param name="configureDefaultHeaders">Delegate to add default headers to the wrapped HttpClient instance</param>
/// <param name="configureSerialization">Delegate to configure serialization</param>
public RestClient(ConfigureRestClient? configureRestClient = null, ConfigureSerialization? configureSerialization = null)
: this(ConfigureOptions(new RestClientOptions(), configureRestClient), configureSerialization: configureSerialization) { }
public RestClient(
ConfigureRestClient? configureRestClient = null,
ConfigureHeaders? configureDefaultHeaders = null,
ConfigureSerialization? configureSerialization = null
)
: this(ConfigureOptions(new RestClientOptions(), configureRestClient), configureDefaultHeaders, configureSerialization) { }

/// <inheritdoc />
/// <summary>
/// Creates an instance of RestClient using a specific BaseUrl for requests made by this client instance
/// </summary>
/// <param name="baseUrl">Base URI for the new client</param>
/// <param name="configureRestClient">Delegate to configure the client options</param>
/// <param name="configureDefaultHeaders">Delegate to add default headers to the wrapped HttpClient instance</param>
/// <param name="configureSerialization">Delegate to configure serialization</param>
public RestClient(Uri baseUrl, ConfigureRestClient? configureRestClient = null, ConfigureSerialization? configureSerialization = null)
: this(ConfigureOptions(new RestClientOptions { BaseUrl = baseUrl }, configureRestClient), configureSerialization: configureSerialization) { }
public RestClient(
Uri baseUrl,
ConfigureRestClient? configureRestClient = null,
ConfigureHeaders? configureDefaultHeaders = null,
ConfigureSerialization? configureSerialization = null
)
: this(
ConfigureOptions(new RestClientOptions { BaseUrl = baseUrl }, configureRestClient),
configureDefaultHeaders,
configureSerialization
) { }

/// <summary>
/// Creates an instance of RestClient using a specific BaseUrl for requests made by this client instance
/// </summary>
/// <param name="baseUrl">Base URI for this new client as a string</param>
/// <param name="configureRestClient">Delegate to configure the client options</param>
/// <param name="configureDefaultHeaders">Delegate to add default headers to the wrapped HttpClient instance</param>
/// <param name="configureSerialization">Delegate to configure serialization</param>
public RestClient(string baseUrl, ConfigureRestClient? configureRestClient = null, ConfigureSerialization? configureSerialization = null)
: this(new Uri(Ensure.NotEmptyString(baseUrl, nameof(baseUrl))), configureRestClient, configureSerialization) { }
public RestClient(
string baseUrl,
ConfigureRestClient? configureRestClient = null,
ConfigureHeaders? configureDefaultHeaders = null,
ConfigureSerialization? configureSerialization = null
)
: this(new Uri(Ensure.NotEmptyString(baseUrl, nameof(baseUrl))), configureRestClient, configureDefaultHeaders, configureSerialization) { }

/// <summary>
/// Creates an instance of RestClient using a shared HttpClient and specific RestClientOptions and does not allocate one internally.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ public async Task Can_Authenticate_With_Basic_Http_Auth() {
const string userName = "testuser";
const string password = "testpassword";

var client = new RestClient(_fixture.Server.Url, o =>
o.Authenticator = new HttpBasicAuthenticator(userName, password)
var client = new RestClient(
_fixture.Server.Url,
o => o.Authenticator = new HttpBasicAuthenticator(userName, password)
);
var request = new RestRequest("headers");
var response = await client.GetAsync<TestServerResponse[]>(request);
Expand All @@ -34,4 +35,4 @@ public async Task Can_Authenticate_With_Basic_Http_Auth() {
parts[0].Should().Be(userName);
parts[1].Should().Be(password);
}
}
}
8 changes: 3 additions & 5 deletions test/RestSharp.Tests.Integrated/Authentication/OAuth2Tests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using RestSharp.Authenticators.OAuth2;
using RestSharp.Tests.Integrated.Fixtures;
using RestSharp.Tests.Integrated.Server;

namespace RestSharp.Tests.Integrated.Authentication;
namespace RestSharp.Tests.Integrated.Authentication;

[Collection(nameof(TestServerCollection))]
public class OAuth2Tests {
Expand All @@ -12,14 +11,13 @@ public class OAuth2Tests {

[Fact]
public async Task ShouldHaveProperHeader() {
var client = new RestClient(_fixture.Server.Url);
var auth = new OAuth2AuthorizationRequestHeaderAuthenticator("token", "Bearer");
client.Authenticator = auth;
var client = new RestClient(_fixture.Server.Url, o => o.Authenticator = auth);

var response = await client.GetJsonAsync<TestServerResponse[]>("headers");
var authHeader = response!.FirstOrDefault(x => x.Name == KnownHeaders.Authorization);

authHeader.Should().NotBeNull();
authHeader!.Value.Should().Be("Bearer token");
}
}
}
51 changes: 51 additions & 0 deletions test/RestSharp.Tests.Integrated/CookieTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System.Net;
using RestSharp.Tests.Integrated.Server;

namespace RestSharp.Tests.Integrated;

[Collection(nameof(TestServerCollection))]
public class CookieTests {
readonly RestClient _client;
readonly string _host;

public CookieTests(TestServerFixture fixture) {
_client = new RestClient(fixture.Server.Url);
_host = _client.Options.BaseUrl!.Host;
}

[Fact]
public async Task Can_Perform_GET_Async_With_Request_Cookies() {
var request = new RestRequest("get-cookies") {
CookieContainer = new CookieContainer()
};
request.CookieContainer.Add(new Cookie("cookie", "value", null, _host));
request.CookieContainer.Add(new Cookie("cookie2", "value2", null, _host));
var response = await _client.ExecuteAsync(request);
response.Content.Should().Be("[\"cookie=value\",\"cookie2=value2\"]");
}

[Fact]
public async Task Can_Perform_GET_Async_With_Response_Cookies() {
var request = new RestRequest("set-cookies");
var response = await _client.ExecuteAsync(request);
response.Content.Should().Be("success");

AssertCookie("cookie1", "value1", x => x == DateTime.MinValue);
FindCookie("cookie2").Should().BeNull("Cookie 2 should vanish as the path will not match");
AssertCookie("cookie3", "value3", x => x > DateTime.Now);
AssertCookie("cookie4", "value4", x => x > DateTime.Now);
FindCookie("cookie5").Should().BeNull("Cookie 5 should vanish as the request is not SSL");
AssertCookie("cookie6", "value6", x => x == DateTime.MinValue, true);

Cookie? FindCookie(string name) =>response!.Cookies!.FirstOrDefault(p => p.Name == name);

void AssertCookie(string name, string value, Func<DateTime, bool> checkExpiration, bool httpOnly = false) {
var c = FindCookie(name)!;
c.Value.Should().Be(value);
c.Path.Should().Be("/");
c.Domain.Should().Be(_host);
checkExpiration(c.Expires).Should().BeTrue();
c.HttpOnly.Should().Be(httpOnly);
}
}
}
1 change: 0 additions & 1 deletion test/RestSharp.Tests.Integrated/RequestFailureTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Net;
using RestSharp.Tests.Integrated.Fixtures;
using RestSharp.Tests.Integrated.Server;

namespace RestSharp.Tests.Integrated;
Expand Down
66 changes: 5 additions & 61 deletions test/RestSharp.Tests.Integrated/RequestTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Net;
using RestSharp.Tests.Integrated.Fixtures;
using RestSharp.Tests.Integrated.Server;

namespace RestSharp.Tests.Integrated;
Expand All @@ -8,10 +7,12 @@ namespace RestSharp.Tests.Integrated;
public class AsyncTests {
readonly ITestOutputHelper _output;
readonly RestClient _client;
readonly string _host;

public AsyncTests(TestServerFixture fixture, ITestOutputHelper output) {
_output = output;
_client = new RestClient(fixture.Server.Url);
_output = output;
_client = new RestClient(fixture.Server.Url);
_host = _client.Options.BaseUrl!.Host;
}

class Response {
Expand Down Expand Up @@ -51,63 +52,6 @@ public async Task Can_Perform_GET_Async() {
response.Content.Should().Be(val);
}

[Fact]
public async Task Can_Perform_GET_Async_With_Request_Cookies() {
var request = new RestRequest("get-cookies") {
CookieContainer = new CookieContainer()
};
request.CookieContainer.Add(new Cookie("cookie", "value", null, _client.Options.BaseUrl.Host));
request.CookieContainer.Add(new Cookie("cookie2", "value2", null, _client.Options.BaseUrl.Host));
var response = await _client.ExecuteAsync(request);
response.Content.Should().Be("[\"cookie=value\",\"cookie2=value2\"]");
}

[Fact]
public async Task Can_Perform_GET_Async_With_Response_Cookies() {
var request = new RestRequest("set-cookies");
var response = await _client.ExecuteAsync(request);
response.Content.Should().Be("success");

// Check we got all our cookies
var domain = _client.Options.BaseUrl.Host;
var cookie = response.Cookies!.First(p => p.Name == "cookie1");
Assert.Equal("value1", cookie.Value);
Assert.Equal("/", cookie.Path);
Assert.Equal(domain, cookie.Domain);
Assert.Equal(DateTime.MinValue, cookie.Expires);
Assert.False(cookie.HttpOnly);

// Cookie 2 should vanish as the path will not match
cookie = response.Cookies!.FirstOrDefault(p => p.Name == "cookie2");
Assert.Null(cookie);

// Check cookie3 has a valid expiration
cookie = response.Cookies!.First(p => p.Name == "cookie3");
Assert.Equal("value3", cookie.Value);
Assert.Equal("/", cookie.Path);
Assert.Equal(domain, cookie.Domain);
Assert.True(cookie.Expires > DateTime.Now);

// Check cookie4 has a valid expiration
cookie = response.Cookies!.First(p => p.Name == "cookie4");
Assert.Equal("value4", cookie.Value);
Assert.Equal("/", cookie.Path);
Assert.Equal(domain, cookie.Domain);
Assert.True(cookie.Expires > DateTime.Now);

// Cookie 5 should vanish as the request is not SSL
cookie = response.Cookies!.FirstOrDefault(p => p.Name == "cookie5");
Assert.Null(cookie);

// Check cookie6 should be http only
cookie = response.Cookies!.First(p => p.Name == "cookie6");
Assert.Equal("value6", cookie.Value);
Assert.Equal("/", cookie.Path);
Assert.Equal(domain, cookie.Domain);
Assert.Equal(DateTime.MinValue, cookie.Expires);
Assert.True(cookie.HttpOnly);
}

[Fact]
public async Task Can_Timeout_GET_Async() {
var request = new RestRequest("timeout").AddBody("Body_Content");
Expand Down Expand Up @@ -136,4 +80,4 @@ public async Task Can_Delete_With_Response_Type_using_extension() {

response!.Message.Should().Be("Works!");
}
}
}
26 changes: 13 additions & 13 deletions test/RestSharp.Tests.Integrated/RestSharp.Tests.Integrated.csproj
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Nullable>disable</Nullable>
<Nullable>enable</Nullable>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\RestSharp.Serializers.Xml\RestSharp.Serializers.Xml.csproj"/>
<ProjectReference Include="..\..\src\RestSharp\RestSharp.csproj"/>
<ProjectReference Include="..\RestSharp.Tests.Shared\RestSharp.Tests.Shared.csproj"/>
<ProjectReference Include="..\..\src\RestSharp.Serializers.Xml\RestSharp.Serializers.Xml.csproj" />
<ProjectReference Include="..\..\src\RestSharp\RestSharp.csproj" />
<ProjectReference Include="..\RestSharp.Tests.Shared\RestSharp.Tests.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Assets\Koala.jpg" CopyToOutputDirectory="PreserveNewest"/>
<None Update="Assets\TestFile.txt" CopyToOutputDirectory="PreserveNewest"/>
<None Update="Assets\KoalaÄÖäö.jpg" CopyToOutputDirectory="PreserveNewest"/>
<None Update="Assets\Teståæ.txt" CopyToOutputDirectory="PreserveNewest"/>
<None Update="Assets\Koala.jpg" CopyToOutputDirectory="PreserveNewest" />
<None Update="Assets\TestFile.txt" CopyToOutputDirectory="PreserveNewest" />
<None Update="Assets\KoalaÄÖäö.jpg" CopyToOutputDirectory="PreserveNewest" />
<None Update="Assets\Teståæ.txt" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="HttpTracer" Version="2.1.1"/>
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="6.0.9"/>
<PackageReference Include="Polly" Version="7.2.3"/>
<PackageReference Include="Xunit.Extensions.Logging" Version="1.1.0"/>
<PackageReference Include="HttpTracer" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="6.0.9" />
<PackageReference Include="Polly" Version="7.2.3" />
<PackageReference Include="Xunit.Extensions.Logging" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<None Update="xunit.runner.json" CopyToOutputDirectory="PreserveNewest"/>
<None Update="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>
Loading