Moving folder structure

This commit is contained in:
2025-07-10 10:12:50 +02:00
parent 450aa5f1c9
commit 29f6c4ae81
172 changed files with 109 additions and 162 deletions

View File

@@ -0,0 +1,79 @@
using System.Linq;
using System.Net.Http;
using AMWD.Net.Api.Cloudflare;
namespace Cloudflare.Core.Tests.Auth
{
[TestClass]
public class ApiKeyAuthenticationTest
{
[TestMethod]
public void ShouldAddHeaders()
{
// Arrange
string emailAddress = "test@example.com";
string apiKey = "some-api-key";
var auth = new ApiKeyAuthentication(emailAddress, apiKey);
using var clt = new HttpClient();
// Act
auth.AddHeader(clt);
// Assert
Assert.IsTrue(clt.DefaultRequestHeaders.Contains("X-Auth-Email"));
Assert.IsTrue(clt.DefaultRequestHeaders.Contains("X-Auth-Key"));
Assert.AreEqual(emailAddress, clt.DefaultRequestHeaders.GetValues("X-Auth-Email").First());
Assert.AreEqual(apiKey, clt.DefaultRequestHeaders.GetValues("X-Auth-Key").First());
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public void ShouldArgumentNullExceptionForEmailAddress(string emailAddress)
{
// Arrange
string apiKey = "some-api-key";
// Act
new ApiKeyAuthentication(emailAddress, apiKey);
// Assert - ArgumentNullException
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public void ShouldArgumentNullExceptionForApiKey(string apiKey)
{
// Arrange
string emailAddress = "test@example.com";
// Act
new ApiKeyAuthentication(emailAddress, apiKey);
// Assert - ArgumentNullException
}
[DataTestMethod]
[DataRow("test")]
[DataRow("test@example")]
[DataRow("example.com")]
[ExpectedException(typeof(ArgumentException))]
public void ShouldArgumentExceptionForInvalidEmailAddress(string emailAddress)
{
// Arrange
string apiKey = "some-api-key";
// Act
new ApiKeyAuthentication(emailAddress, apiKey);
// Assert - ArgumentException
}
}
}

View File

@@ -0,0 +1,43 @@
using System.Net.Http;
using AMWD.Net.Api.Cloudflare;
namespace Cloudflare.Core.Tests.Auth
{
[TestClass]
public class ApiTokenAuthenticationTest
{
[TestMethod]
public void ShouldAddHeader()
{
// Arrange
string apiToken = "some-api-token";
var auth = new ApiTokenAuthentication(apiToken);
using var clt = new HttpClient();
// Act
auth.AddHeader(clt);
// Assert
Assert.IsTrue(clt.DefaultRequestHeaders.Contains("Authorization"));
Assert.AreEqual("Bearer", clt.DefaultRequestHeaders.Authorization.Scheme);
Assert.AreEqual(apiToken, clt.DefaultRequestHeaders.Authorization.Parameter);
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public void ShouldArgumentNullExceptionForEmailAddress(string apiToken)
{
// Arrange
// Act
new ApiTokenAuthentication(apiToken);
// Assert - ArgumentNullException
}
}
}

View File

@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,248 @@
using System.Linq;
using System.Net.Http;
using System.Reflection;
using AMWD.Net.Api.Cloudflare;
using Moq;
using Moq.Protected;
namespace Cloudflare.Core.Tests
{
[TestClass]
public class CloudflareClientTest
{
private Mock<HttpMessageHandler> _httpHandlerMock;
private Mock<ClientOptions> _clientOptionsMock;
private Mock<IAuthentication> _authenticationMock;
[TestInitialize]
public void Initialize()
{
_httpHandlerMock = new Mock<HttpMessageHandler>();
_authenticationMock = new Mock<IAuthentication>();
_clientOptionsMock = new Mock<ClientOptions>();
_clientOptionsMock.Setup(o => o.BaseUrl).Returns("http://localhost/api/v4/");
_clientOptionsMock.Setup(o => o.Timeout).Returns(TimeSpan.FromSeconds(60));
_clientOptionsMock.Setup(o => o.MaxRetries).Returns(2);
_clientOptionsMock.Setup(o => o.DefaultHeaders).Returns(new Dictionary<string, string>());
_clientOptionsMock.Setup(o => o.DefaultQueryParams).Returns(new Dictionary<string, string>());
_clientOptionsMock.Setup(o => o.AllowRedirects).Returns(false);
_clientOptionsMock.Setup(o => o.UseProxy).Returns(false);
}
[TestMethod]
public void ShouldInitializeWithEmailAndKey()
{
// Arrange
string email = "test@example.com";
string apiKey = "some-api-key";
// Act
using var client = new CloudflareClient(email, apiKey);
// Assert
var httpClient = client.GetType()
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(client) as HttpClient;
Assert.IsNotNull(httpClient);
Assert.AreEqual(email, httpClient.DefaultRequestHeaders.GetValues("X-Auth-Email").First());
Assert.AreEqual(apiKey, httpClient.DefaultRequestHeaders.GetValues("X-Auth-Key").First());
VerifyNoOtherCalls();
}
[TestMethod]
public void ShouldInitializeWithApiToken()
{
// Arrange
string token = "some-special-api-token";
// Act
using var client = new CloudflareClient(token);
// Assert
var httpClient = client.GetType()
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(client) as HttpClient;
Assert.IsNotNull(httpClient);
Assert.AreEqual($"Bearer {token}", httpClient.DefaultRequestHeaders.GetValues("Authorization").First());
VerifyNoOtherCalls();
}
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowArgumentNullOnMissingAuthentication()
{
// Arrange
// Act
using var client = new CloudflareClient((IAuthentication)null);
// Assert - ArgumentNullException
}
[TestMethod]
public void ShouldAddCustomDefaultHeaders()
{
// Arrange
var clientOptions = new ClientOptions();
clientOptions.DefaultHeaders.Add("SomeKey", "SomeValue");
// Act
using var client = new CloudflareClient("token", clientOptions);
// Assert
var httpClient = client.GetType()
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(client) as HttpClient;
Assert.IsNotNull(httpClient);
Assert.IsTrue(httpClient.DefaultRequestHeaders.Contains("SomeKey"));
Assert.AreEqual("SomeValue", httpClient.DefaultRequestHeaders.GetValues("SomeKey").First());
VerifyNoOtherCalls();
}
[TestMethod]
public void ShouldDisposeHttpClient()
{
// Arrange
var client = GetClient();
// Act
client.Dispose();
// Assert
_httpHandlerMock.Protected().Verify("Dispose", Times.Once(), exactParameterMatch: true, true);
VerifyDefault();
VerifyNoOtherCalls();
}
[TestMethod]
public void ShouldAllowMultipleDispose()
{
// Arrange
var client = GetClient();
// Act
client.Dispose();
client.Dispose();
// Assert
_httpHandlerMock.Protected().Verify("Dispose", Times.Once(), exactParameterMatch: true, true);
VerifyDefault();
VerifyNoOtherCalls();
}
[TestMethod]
public void ShouldAssertClientOptions()
{
// Arrange + Act
var client = GetClient();
// Assert
VerifyDefault();
VerifyNoOtherCalls();
}
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowArgumentNullForBaseUrlOnAssertClientOptions()
{
// Arrange
_clientOptionsMock
.Setup(o => o.BaseUrl)
.Returns((string)null);
// Act
var client = GetClient();
// Assert - ArgumentNullException
}
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void ShouldThrowArgumentOutOfRangeForTimeoutOnAssertClientOptions()
{
// Arrange
_clientOptionsMock
.Setup(o => o.Timeout)
.Returns(TimeSpan.Zero);
// Act
var client = GetClient();
// Assert - ArgumentOutOfRangeException
}
[DataTestMethod]
[DataRow(-1)]
[DataRow(11)]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void ShouldThrowArgumentOutOfRangeForMaxRetriesOnAssertClientOptions(int maxRetries)
{
// Arrange
_clientOptionsMock
.Setup(o => o.MaxRetries)
.Returns(maxRetries);
// Act
var client = GetClient();
// Assert - ArgumentOutOfRangeException
}
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowArgumentNullForUseProxyOnAssertClientOptions()
{
// Arrange
_clientOptionsMock
.Setup(o => o.UseProxy)
.Returns(true);
// Act
var client = GetClient();
// Assert - ArgumentNullException
}
private void VerifyDefault()
{
_clientOptionsMock.VerifyGet(o => o.AllowRedirects, Times.Once);
_clientOptionsMock.VerifyGet(o => o.BaseUrl, Times.Exactly(2));
_clientOptionsMock.VerifyGet(o => o.DefaultHeaders, Times.Once);
_clientOptionsMock.VerifyGet(o => o.MaxRetries, Times.Exactly(2));
_clientOptionsMock.VerifyGet(o => o.Proxy, Times.Once);
_clientOptionsMock.VerifyGet(o => o.Timeout, Times.Exactly(2));
_clientOptionsMock.VerifyGet(o => o.UseProxy, Times.Exactly(2));
_authenticationMock.Verify(a => a.AddHeader(It.IsAny<HttpClient>()), Times.Once);
}
private void VerifyNoOtherCalls()
{
_httpHandlerMock.VerifyNoOtherCalls();
_clientOptionsMock.VerifyNoOtherCalls();
_authenticationMock.VerifyNoOtherCalls();
}
private CloudflareClient GetClient()
{
var httpClient = new HttpClient(_httpHandlerMock.Object);
var client = new CloudflareClient(_authenticationMock.Object, _clientOptionsMock.Object);
var httpClientField = client.GetType()
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
(httpClientField.GetValue(client) as HttpClient).Dispose();
httpClientField.SetValue(client, httpClient);
return client;
}
}
}

View File

@@ -0,0 +1,315 @@
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Reflection;
using System.Security.Authentication;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using Moq;
using Moq.Protected;
namespace Cloudflare.Core.Tests.CloudflareClientTests
{
[TestClass]
public class DeleteAsyncTest
{
private const string BaseUrl = "http://localhost/api/v4/";
private HttpMessageHandlerMock _httpHandlerMock;
private Mock<ClientOptions> _clientOptionsMock;
private Mock<IAuthentication> _authenticationMock;
[TestInitialize]
public void Initialize()
{
_httpHandlerMock = new HttpMessageHandlerMock();
_authenticationMock = new Mock<IAuthentication>();
_clientOptionsMock = new Mock<ClientOptions>();
_authenticationMock
.Setup(a => a.AddHeader(It.IsAny<HttpClient>()))
.Callback<HttpClient>(c => c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Some-API-Token"));
_clientOptionsMock.Setup(o => o.BaseUrl).Returns(BaseUrl);
_clientOptionsMock.Setup(o => o.Timeout).Returns(TimeSpan.FromSeconds(60));
_clientOptionsMock.Setup(o => o.MaxRetries).Returns(2);
_clientOptionsMock.Setup(o => o.DefaultHeaders).Returns(new Dictionary<string, string>());
_clientOptionsMock.Setup(o => o.DefaultQueryParams).Returns(new Dictionary<string, string>());
_clientOptionsMock.Setup(o => o.AllowRedirects).Returns(false);
_clientOptionsMock.Setup(o => o.UseProxy).Returns(false);
}
[TestMethod]
[ExpectedException(typeof(ObjectDisposedException))]
public async Task ShouldThrowDisposed()
{
// Arrange
var client = GetClient() as CloudflareClient;
client.Dispose();
// Act
await client.DeleteAsync<object>("test");
// Assert - ObjectDisposedException
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public async Task ShouldThrowArgumentNullOnRequestPath(string path)
{
// Arrange
var client = GetClient();
// Act
await client.DeleteAsync<object>(path);
// Assert - ArgumentNullException
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public async Task ShouldThrowArgumentOnRequestPath()
{
// Arrange
var client = GetClient();
// Act
await client.DeleteAsync<object>("foo?bar=baz");
// Assert - ArgumentException
}
[TestMethod]
public async Task ShouldDelete()
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(@"{""success"": true, ""errors"": [], ""messages"": [], ""result"": { ""string"": ""some-string"", ""integer"": 123 }}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
// Act
var response = await client.DeleteAsync<TestClass>("test");
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNotNull(response.Errors);
Assert.IsNotNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual(0, response.Errors.Count);
Assert.AreEqual(0, response.Messages.Count);
Assert.IsNotNull(response.Result);
Assert.AreEqual("some-string", response.Result.Str);
Assert.AreEqual(123, response.Result.Int);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Delete, callback.Method);
Assert.AreEqual("http://localhost/api/v4/test", callback.Url);
Assert.IsNull(callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
VerifyDefaults();
VerifyNoOtherCalls();
}
[DataTestMethod]
[DataRow(HttpStatusCode.Unauthorized)]
[DataRow(HttpStatusCode.Forbidden)]
public async Task ShouldThrowAuthenticationExceptionOnStatusCode(HttpStatusCode statusCode)
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = statusCode,
Content = new StringContent(@"{""success"": false, ""errors"": [{ ""code"": ""4711"", ""message"": ""foo & baz."" }, { ""code"": ""4712"", ""message"": ""Happy Error!"" }], ""messages"": []}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
try
{
// Act
await client.DeleteAsync<TestClass>("foo");
Assert.Fail();
}
catch (AuthenticationException ex)
{
// Assert
Assert.IsNull(ex.InnerException);
Assert.AreEqual($"4711: foo & baz.{Environment.NewLine}4712: Happy Error!", ex.Message);
}
}
[TestMethod]
public async Task ShouldReturnPlainText()
{
// Arrange
_clientOptionsMock.Setup(o => o.DefaultQueryParams).Returns(new Dictionary<string, string> { { "bar", "08/15" } });
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("This is an awesome text ;-)", Encoding.UTF8, MediaTypeNames.Text.Plain),
});
var client = GetClient();
// Act
var response = await client.DeleteAsync<string>("some-awesome-path");
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNull(response.Errors);
Assert.IsNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual("This is an awesome text ;-)", response.Result);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Delete, callback.Method);
Assert.AreEqual("http://localhost/api/v4/some-awesome-path?bar=08%2F15", callback.Url);
Assert.IsNull(callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
_authenticationMock.Verify(m => m.AddHeader(It.IsAny<HttpClient>()), Times.Once);
_clientOptionsMock.Verify(o => o.BaseUrl, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Timeout, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.MaxRetries, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.DefaultHeaders, Times.Once);
_clientOptionsMock.Verify(o => o.DefaultQueryParams, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.AllowRedirects, Times.Once);
_clientOptionsMock.Verify(o => o.UseProxy, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Proxy, Times.Once);
VerifyNoOtherCalls();
}
[TestMethod]
[ExpectedException(typeof(JsonReaderException))]
public async Task ShouldThrowExceptionOnInvalidResponse()
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("This is a bad text :p", Encoding.UTF8, MediaTypeNames.Text.Plain),
});
var client = GetClient();
// Act
await client.DeleteAsync<TestClass>("some-path");
}
private void VerifyDefaults()
{
_authenticationMock.Verify(m => m.AddHeader(It.IsAny<HttpClient>()), Times.Once);
_clientOptionsMock.Verify(o => o.BaseUrl, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Timeout, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.MaxRetries, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.DefaultHeaders, Times.Once);
_clientOptionsMock.Verify(o => o.DefaultQueryParams, Times.Once);
_clientOptionsMock.Verify(o => o.AllowRedirects, Times.Once);
_clientOptionsMock.Verify(o => o.UseProxy, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Proxy, Times.Once);
}
private void VerifyNoOtherCalls()
{
_httpHandlerMock.Mock.VerifyNoOtherCalls();
_authenticationMock.VerifyNoOtherCalls();
_clientOptionsMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
var httpClient = new HttpClient(_httpHandlerMock.Mock.Object)
{
Timeout = _clientOptionsMock.Object.Timeout,
BaseAddress = new Uri(BaseUrl),
};
httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("AMWD.CloudflareClient", "1.0.0"));
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (_clientOptionsMock.Object.DefaultHeaders.Count > 0)
{
foreach (var headerKvp in _clientOptionsMock.Object.DefaultHeaders)
httpClient.DefaultRequestHeaders.Add(headerKvp.Key, headerKvp.Value);
}
_authenticationMock.Object.AddHeader(httpClient);
_authenticationMock.Invocations.Clear();
_clientOptionsMock.Invocations.Clear();
var client = new CloudflareClient(_authenticationMock.Object, _clientOptionsMock.Object);
var httpClientField = client.GetType()
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
(httpClientField.GetValue(client) as HttpClient).Dispose();
httpClientField.SetValue(client, httpClient);
return client;
}
private class TestClass
{
[JsonProperty("string")]
public string Str { get; set; }
[JsonProperty("integer")]
public int Int { get; set; }
}
private class TestFilter : IQueryParameterFilter
{
public IDictionary<string, string> GetQueryParameters()
{
return new Dictionary<string, string>
{
{ "test", "filter-text" }
};
}
}
}
}

View File

@@ -0,0 +1,355 @@
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Reflection;
using System.Security.Authentication;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using Moq;
using Moq.Protected;
namespace Cloudflare.Core.Tests.CloudflareClientTests
{
[TestClass]
public class GetAsyncTest
{
private const string BaseUrl = "http://localhost/api/v4/";
private HttpMessageHandlerMock _httpHandlerMock;
private Mock<ClientOptions> _clientOptionsMock;
private Mock<IAuthentication> _authenticationMock;
[TestInitialize]
public void Initialize()
{
_httpHandlerMock = new HttpMessageHandlerMock();
_authenticationMock = new Mock<IAuthentication>();
_clientOptionsMock = new Mock<ClientOptions>();
_authenticationMock
.Setup(a => a.AddHeader(It.IsAny<HttpClient>()))
.Callback<HttpClient>(c => c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Some-API-Token"));
_clientOptionsMock.Setup(o => o.BaseUrl).Returns(BaseUrl);
_clientOptionsMock.Setup(o => o.Timeout).Returns(TimeSpan.FromSeconds(60));
_clientOptionsMock.Setup(o => o.MaxRetries).Returns(2);
_clientOptionsMock.Setup(o => o.DefaultHeaders).Returns(new Dictionary<string, string>());
_clientOptionsMock.Setup(o => o.DefaultQueryParams).Returns(new Dictionary<string, string>());
_clientOptionsMock.Setup(o => o.AllowRedirects).Returns(false);
_clientOptionsMock.Setup(o => o.UseProxy).Returns(false);
}
[TestMethod]
[ExpectedException(typeof(ObjectDisposedException))]
public async Task ShouldThrowDisposed()
{
// Arrange
var client = GetClient() as CloudflareClient;
client.Dispose();
// Act
await client.GetAsync<object>("/test");
// Assert - ObjectDisposedException
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public async Task ShouldThrowArgumentNullOnRequestPath(string path)
{
// Arrange
var client = GetClient();
// Act
await client.GetAsync<object>(path);
// Assert - ArgumentNullException
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public async Task ShouldThrowArgumentOnRequestPath()
{
// Arrange
var client = GetClient();
// Act
await client.GetAsync<object>("/foo?bar=baz");
// Assert - ArgumentException
}
[TestMethod]
public async Task ShouldGet()
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(@"{""success"": true, ""errors"": [], ""messages"": [], ""result"": { ""string"": ""some-string"", ""integer"": 123 }}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
// Act
var response = await client.GetAsync<TestClass>("test");
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNotNull(response.Errors);
Assert.IsNotNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual(0, response.Errors.Count);
Assert.AreEqual(0, response.Messages.Count);
Assert.IsNotNull(response.Result);
Assert.AreEqual("some-string", response.Result.Str);
Assert.AreEqual(123, response.Result.Int);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Get, callback.Method);
Assert.AreEqual("http://localhost/api/v4/test", callback.Url);
Assert.IsNull(callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
VerifyDefaults();
VerifyNoOtherCalls();
}
[DataTestMethod]
[DataRow(HttpStatusCode.Unauthorized)]
[DataRow(HttpStatusCode.Forbidden)]
public async Task ShouldThrowAuthenticationExceptionOnStatusCode(HttpStatusCode statusCode)
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = statusCode,
Content = new StringContent(@"{""success"": false, ""errors"": [{ ""code"": ""4711"", ""message"": ""foo & baz."" }, { ""code"": ""4712"", ""message"": ""Happy Error!"" }], ""messages"": []}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
try
{
// Act
await client.GetAsync<TestClass>("foo");
Assert.Fail();
}
catch (AuthenticationException ex)
{
// Assert
Assert.IsNull(ex.InnerException);
Assert.AreEqual($"4711: foo & baz.{Environment.NewLine}4712: Happy Error!", ex.Message);
}
}
[DataTestMethod]
[DataRow(HttpStatusCode.Unauthorized)]
[DataRow(HttpStatusCode.Forbidden)]
[ExpectedException(typeof(CloudflareException))]
public async Task ShouldThrowCloudflareExceptionOnStatusCodeWhenDeserializeFails(HttpStatusCode statusCode)
{
// Arrange
_httpHandlerMock?.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = statusCode,
Content = new StringContent("", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
// Act
await client.GetAsync<TestClass>("foo");
// Assert - CloudflareException
}
[TestMethod]
public async Task ShouldReturnPlainText()
{
// Arrange
_clientOptionsMock.Setup(o => o.DefaultQueryParams).Returns(new Dictionary<string, string> { { "bar", "08/15" } });
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("This is an awesome text ;-)", Encoding.UTF8, MediaTypeNames.Text.Plain),
});
var client = GetClient();
// Act
var response = await client.GetAsync<string>("some-awesome-path", new TestFilter());
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNull(response.Errors);
Assert.IsNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual("This is an awesome text ;-)", response.Result);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Get, callback.Method);
Assert.AreEqual("http://localhost/api/v4/some-awesome-path?bar=08%2F15&test=filter-text", callback.Url);
Assert.IsNull(callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
_authenticationMock.Verify(m => m.AddHeader(It.IsAny<HttpClient>()), Times.Once);
_clientOptionsMock.Verify(o => o.BaseUrl, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Timeout, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.MaxRetries, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.DefaultHeaders, Times.Once);
_clientOptionsMock.Verify(o => o.DefaultQueryParams, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.AllowRedirects, Times.Once);
_clientOptionsMock.Verify(o => o.UseProxy, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Proxy, Times.Once);
VerifyNoOtherCalls();
}
[TestMethod]
[ExpectedException(typeof(JsonReaderException))]
public async Task ShouldThrowExceptionOnInvalidResponse()
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("This is a bad text :p", Encoding.UTF8, MediaTypeNames.Text.Plain),
});
var client = GetClient();
// Act
await client.GetAsync<TestClass>("some-path");
}
[TestMethod]
[ExpectedException(typeof(CloudflareException))]
public async Task ShouldThrowCloudflareExceptionWhenDeserializeFails()
{
// Arrange
_httpHandlerMock?.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
// Act
await client.GetAsync<TestClass>("foo");
// Assert - CloudflareException
}
private void VerifyDefaults()
{
_authenticationMock.Verify(m => m.AddHeader(It.IsAny<HttpClient>()), Times.Once);
_clientOptionsMock.Verify(o => o.BaseUrl, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Timeout, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.MaxRetries, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.DefaultHeaders, Times.Once);
_clientOptionsMock.Verify(o => o.DefaultQueryParams, Times.Once);
_clientOptionsMock.Verify(o => o.AllowRedirects, Times.Once);
_clientOptionsMock.Verify(o => o.UseProxy, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Proxy, Times.Once);
}
private void VerifyNoOtherCalls()
{
_httpHandlerMock.Mock.VerifyNoOtherCalls();
_authenticationMock.VerifyNoOtherCalls();
_clientOptionsMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
var httpClient = new HttpClient(_httpHandlerMock.Mock.Object)
{
Timeout = _clientOptionsMock.Object.Timeout,
BaseAddress = new Uri(BaseUrl),
};
httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("AMWD.CloudflareClient", "1.0.0"));
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (_clientOptionsMock.Object.DefaultHeaders.Count > 0)
{
foreach (var headerKvp in _clientOptionsMock.Object.DefaultHeaders)
httpClient.DefaultRequestHeaders.Add(headerKvp.Key, headerKvp.Value);
}
_authenticationMock.Object.AddHeader(httpClient);
_authenticationMock.Invocations.Clear();
_clientOptionsMock.Invocations.Clear();
var client = new CloudflareClient(_authenticationMock.Object, _clientOptionsMock.Object);
var httpClientField = client.GetType()
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
(httpClientField.GetValue(client) as HttpClient).Dispose();
httpClientField.SetValue(client, httpClient);
return client;
}
private class TestClass
{
[JsonProperty("string")]
public string Str { get; set; }
[JsonProperty("integer")]
public int Int { get; set; }
}
private class TestFilter : IQueryParameterFilter
{
public IDictionary<string, string> GetQueryParameters()
{
return new Dictionary<string, string>
{
{ "test", "filter-text" }
};
}
}
}
}

View File

@@ -0,0 +1,375 @@
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Reflection;
using System.Security.Authentication;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using Moq;
using Moq.Protected;
namespace Cloudflare.Core.Tests.CloudflareClientTests
{
[TestClass]
public class PatchAsyncTest
{
private const string BaseUrl = "https://localhost/api/v4/";
private HttpMessageHandlerMock _httpHandlerMock;
private Mock<ClientOptions> _clientOptionsMock;
private Mock<IAuthentication> _authenticationMock;
private TestClass _request;
[TestInitialize]
public void Initialize()
{
_httpHandlerMock = new HttpMessageHandlerMock();
_authenticationMock = new Mock<IAuthentication>();
_clientOptionsMock = new Mock<ClientOptions>();
_authenticationMock
.Setup(a => a.AddHeader(It.IsAny<HttpClient>()))
.Callback<HttpClient>(c => c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Some-API-Token"));
_clientOptionsMock.Setup(o => o.BaseUrl).Returns(BaseUrl);
_clientOptionsMock.Setup(o => o.Timeout).Returns(TimeSpan.FromSeconds(60));
_clientOptionsMock.Setup(o => o.MaxRetries).Returns(2);
_clientOptionsMock.Setup(o => o.DefaultHeaders).Returns(new Dictionary<string, string>());
_clientOptionsMock.Setup(o => o.DefaultQueryParams).Returns(new Dictionary<string, string>());
_clientOptionsMock.Setup(o => o.AllowRedirects).Returns(false);
_clientOptionsMock.Setup(o => o.UseProxy).Returns(false);
_request = new TestClass
{
Int = 54321,
Str = "Happy Testing!"
};
}
[TestMethod]
[ExpectedException(typeof(ObjectDisposedException))]
public async Task ShouldThrowDisposed()
{
// Arrange
var client = GetClient() as CloudflareClient;
client.Dispose();
// Act
await client.PatchAsync<object, object>("test", _request);
// Assert - ObjectDisposedException
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public async Task ShouldThrowArgumentNullOnRequestPath(string path)
{
// Arrange
var client = GetClient();
// Act
await client.PatchAsync<object, object>(path, _request);
// Assert - ArgumentNullException
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public async Task ShouldThrowArgumentOnRequestPath()
{
// Arrange
var client = GetClient();
// Act
await client.PatchAsync<object, object>("foo?bar=baz", _request);
// Assert - ArgumentException
}
[TestMethod]
public async Task ShouldPatch()
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(@"{""success"": true, ""errors"": [], ""messages"": [], ""result"": { ""string"": ""some-string"", ""integer"": 123 }}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
// Act
var response = await client.PatchAsync<TestClass, TestClass>("test", _request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNotNull(response.Errors);
Assert.IsNotNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual(0, response.Errors.Count);
Assert.AreEqual(0, response.Messages.Count);
Assert.IsNotNull(response.Result);
Assert.AreEqual("some-string", response.Result.Str);
Assert.AreEqual(123, response.Result.Int);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Patch, callback.Method);
Assert.AreEqual("https://localhost/api/v4/test", callback.Url);
Assert.AreEqual(@"{""string"":""Happy Testing!"",""integer"":54321}", callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
VerifyDefaults();
VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldPatchHttpContentDirectly()
{
// Arrange
var stringContent = new StringContent(@"{""test"":""HERE ?""}", Encoding.UTF8, "application/json");
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(@"{""success"": true, ""errors"": [], ""messages"": [], ""result"": { ""string"": ""some-string"", ""integer"": 123 }}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
// Act
var response = await client.PatchAsync<TestClass, StringContent>("test", stringContent);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNotNull(response.Errors);
Assert.IsNotNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual(0, response.Errors.Count);
Assert.AreEqual(0, response.Messages.Count);
Assert.IsNotNull(response.Result);
Assert.AreEqual("some-string", response.Result.Str);
Assert.AreEqual(123, response.Result.Int);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Patch, callback.Method);
Assert.AreEqual("https://localhost/api/v4/test", callback.Url);
Assert.AreEqual(@"{""test"":""HERE ?""}", callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
VerifyDefaults();
VerifyNoOtherCalls();
}
[DataTestMethod]
[DataRow(HttpStatusCode.Unauthorized)]
[DataRow(HttpStatusCode.Forbidden)]
public async Task ShouldThrowAuthenticationExceptionOnStatusCode(HttpStatusCode statusCode)
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = statusCode,
Content = new StringContent(@"{""success"": false, ""errors"": [{ ""code"": ""4711"", ""message"": ""foo & baz."" }, { ""code"": ""4712"", ""message"": ""Happy Error!"" }], ""messages"": []}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
try
{
// Act
await client.PatchAsync<object, object>("foo", _request);
Assert.Fail();
}
catch (AuthenticationException ex)
{
// Assert
Assert.IsNull(ex.InnerException);
Assert.AreEqual($"4711: foo & baz.{Environment.NewLine}4712: Happy Error!", ex.Message);
}
}
[TestMethod]
public async Task ShouldReturnPlainText()
{
// Arrange
_clientOptionsMock.Setup(o => o.DefaultQueryParams).Returns(new Dictionary<string, string> { { "bar", "08/15" } });
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("This is an awesome text ;-)", Encoding.UTF8, MediaTypeNames.Text.Plain),
});
var client = GetClient();
// Act
var response = await client.PatchAsync<string, TestClass>("some-awesome-path", _request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNull(response.Errors);
Assert.IsNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual("This is an awesome text ;-)", response.Result);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Patch, callback.Method);
Assert.AreEqual("https://localhost/api/v4/some-awesome-path?bar=08%2F15", callback.Url);
Assert.AreEqual(@"{""string"":""Happy Testing!"",""integer"":54321}", callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
_authenticationMock.Verify(m => m.AddHeader(It.IsAny<HttpClient>()), Times.Once);
_clientOptionsMock.Verify(o => o.BaseUrl, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Timeout, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.MaxRetries, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.DefaultHeaders, Times.Once);
_clientOptionsMock.Verify(o => o.DefaultQueryParams, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.AllowRedirects, Times.Once);
_clientOptionsMock.Verify(o => o.UseProxy, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Proxy, Times.Once);
VerifyNoOtherCalls();
}
[TestMethod]
[ExpectedException(typeof(JsonReaderException))]
public async Task ShouldThrowExceptionOnInvalidResponse()
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("This is a bad text :p", Encoding.UTF8, MediaTypeNames.Text.Plain),
});
var client = GetClient();
// Act
await client.PatchAsync<TestClass, TestClass>("some-path", _request);
}
private void VerifyDefaults()
{
_authenticationMock.Verify(m => m.AddHeader(It.IsAny<HttpClient>()), Times.Once);
_clientOptionsMock.Verify(o => o.BaseUrl, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Timeout, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.MaxRetries, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.DefaultHeaders, Times.Once);
_clientOptionsMock.Verify(o => o.DefaultQueryParams, Times.Once);
_clientOptionsMock.Verify(o => o.AllowRedirects, Times.Once);
_clientOptionsMock.Verify(o => o.UseProxy, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Proxy, Times.Once);
}
private void VerifyNoOtherCalls()
{
_httpHandlerMock.Mock.VerifyNoOtherCalls();
_authenticationMock.VerifyNoOtherCalls();
_clientOptionsMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
var httpClient = new HttpClient(_httpHandlerMock.Mock.Object)
{
Timeout = _clientOptionsMock.Object.Timeout,
BaseAddress = new Uri(BaseUrl),
};
httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("AMWD.CloudflareClient", "1.0.0"));
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (_clientOptionsMock.Object.DefaultHeaders.Count > 0)
{
foreach (var headerKvp in _clientOptionsMock.Object.DefaultHeaders)
httpClient.DefaultRequestHeaders.Add(headerKvp.Key, headerKvp.Value);
}
_authenticationMock.Object.AddHeader(httpClient);
_authenticationMock.Invocations.Clear();
_clientOptionsMock.Invocations.Clear();
var client = new CloudflareClient(_authenticationMock.Object, _clientOptionsMock.Object);
var httpClientField = client.GetType()
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
(httpClientField.GetValue(client) as HttpClient).Dispose();
httpClientField.SetValue(client, httpClient);
return client;
}
private class TestClass
{
[JsonProperty("string")]
public string Str { get; set; }
[JsonProperty("integer")]
public int Int { get; set; }
}
private class TestFilter : IQueryParameterFilter
{
public IDictionary<string, string> GetQueryParameters()
{
return new Dictionary<string, string>
{
{ "test", "filter-text" }
};
}
}
}
}

View File

@@ -0,0 +1,472 @@
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Reflection;
using System.Security.Authentication;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using Moq;
using Moq.Protected;
namespace Cloudflare.Core.Tests.CloudflareClientTests
{
[TestClass]
public class PostAsyncTest
{
private const string BaseUrl = "https://localhost/api/v4/";
private HttpMessageHandlerMock _httpHandlerMock;
private Mock<ClientOptions> _clientOptionsMock;
private Mock<IAuthentication> _authenticationMock;
private TestClass _request;
[TestInitialize]
public void Initialize()
{
_httpHandlerMock = new HttpMessageHandlerMock();
_authenticationMock = new Mock<IAuthentication>();
_clientOptionsMock = new Mock<ClientOptions>();
_authenticationMock
.Setup(a => a.AddHeader(It.IsAny<HttpClient>()))
.Callback<HttpClient>(c => c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Some-API-Token"));
_clientOptionsMock.Setup(o => o.BaseUrl).Returns(BaseUrl);
_clientOptionsMock.Setup(o => o.Timeout).Returns(TimeSpan.FromSeconds(60));
_clientOptionsMock.Setup(o => o.MaxRetries).Returns(2);
_clientOptionsMock.Setup(o => o.DefaultHeaders).Returns(new Dictionary<string, string>());
_clientOptionsMock.Setup(o => o.DefaultQueryParams).Returns(new Dictionary<string, string>());
_clientOptionsMock.Setup(o => o.AllowRedirects).Returns(false);
_clientOptionsMock.Setup(o => o.UseProxy).Returns(false);
_request = new TestClass
{
Int = 54321,
Str = "Happy Testing!"
};
}
[TestMethod]
[ExpectedException(typeof(ObjectDisposedException))]
public async Task ShouldThrowDisposed()
{
// Arrange
var client = GetClient() as CloudflareClient;
client.Dispose();
// Act
await client.PostAsync<object, object>("test", _request);
// Assert - ObjectDisposedException
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public async Task ShouldThrowArgumentNullOnRequestPath(string path)
{
// Arrange
var client = GetClient();
// Act
await client.PostAsync<object, object>(path, _request);
// Assert - ArgumentNullException
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public async Task ShouldThrowArgumentOnRequestPath()
{
// Arrange
var client = GetClient();
// Act
await client.PostAsync<object, object>("foo?bar=baz", _request);
// Assert - ArgumentException
}
[TestMethod]
public async Task ShouldPost()
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(@"{""success"": true, ""errors"": [], ""messages"": [], ""result"": { ""string"": ""some-string"", ""integer"": 123 }}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
// Act
var response = await client.PostAsync<TestClass, TestClass>("test", _request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNotNull(response.Errors);
Assert.IsNotNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual(0, response.Errors.Count);
Assert.AreEqual(0, response.Messages.Count);
Assert.IsNotNull(response.Result);
Assert.AreEqual("some-string", response.Result.Str);
Assert.AreEqual(123, response.Result.Int);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Post, callback.Method);
Assert.AreEqual("https://localhost/api/v4/test", callback.Url);
Assert.AreEqual(@"{""string"":""Happy Testing!"",""integer"":54321}", callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
VerifyDefaults();
VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldPostHttpContentDirectly()
{
// Arrange
var stringContent = new StringContent(@"{""test"":""HERE ?""}", Encoding.UTF8, "application/json");
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(@"{""success"": true, ""errors"": [], ""messages"": [], ""result"": { ""string"": ""some-string"", ""integer"": 123 }}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
// Act
var response = await client.PostAsync<TestClass, StringContent>("test", stringContent);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNotNull(response.Errors);
Assert.IsNotNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual(0, response.Errors.Count);
Assert.AreEqual(0, response.Messages.Count);
Assert.IsNotNull(response.Result);
Assert.AreEqual("some-string", response.Result.Str);
Assert.AreEqual(123, response.Result.Int);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Post, callback.Method);
Assert.AreEqual("https://localhost/api/v4/test", callback.Url);
Assert.AreEqual(@"{""test"":""HERE ?""}", callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
VerifyDefaults();
VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldPostWithoutContent()
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(@"{""success"": true, ""errors"": [], ""messages"": [], ""result"": { ""string"": ""some-string"", ""integer"": 123 }}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
// Act
var response = await client.PostAsync<TestClass, object>("posting", null);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNotNull(response.Errors);
Assert.IsNotNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual(0, response.Errors.Count);
Assert.AreEqual(0, response.Messages.Count);
Assert.IsNotNull(response.Result);
Assert.AreEqual("some-string", response.Result.Str);
Assert.AreEqual(123, response.Result.Int);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Post, callback.Method);
Assert.AreEqual("https://localhost/api/v4/posting", callback.Url);
Assert.IsNull(callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
}
[DataTestMethod]
[DataRow(HttpStatusCode.Unauthorized)]
[DataRow(HttpStatusCode.Forbidden)]
public async Task ShouldThrowAuthenticationExceptionOnStatusCode(HttpStatusCode statusCode)
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = statusCode,
Content = new StringContent(@"{""success"": false, ""errors"": [{ ""code"": ""4711"", ""message"": ""foo & baz."" }, { ""code"": ""4712"", ""message"": ""Happy Error!"" }], ""messages"": []}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
try
{
// Act
await client.PostAsync<object, object>("foo", _request);
Assert.Fail();
}
catch (AuthenticationException ex)
{
// Assert
Assert.IsNull(ex.InnerException);
Assert.AreEqual($"4711: foo & baz.{Environment.NewLine}4712: Happy Error!", ex.Message);
}
}
[TestMethod]
public async Task ShouldReturnPlainText()
{
// Arrange
_clientOptionsMock.Setup(o => o.DefaultQueryParams).Returns(new Dictionary<string, string> { { "bar", "08/15" } });
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("This is an awesome text ;-)", Encoding.UTF8, MediaTypeNames.Text.Plain),
});
var client = GetClient();
// Act
var response = await client.PostAsync<string, TestClass>("some-awesome-path", _request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNull(response.Errors);
Assert.IsNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual("This is an awesome text ;-)", response.Result);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Post, callback.Method);
Assert.AreEqual("https://localhost/api/v4/some-awesome-path?bar=08%2F15", callback.Url);
Assert.AreEqual(@"{""string"":""Happy Testing!"",""integer"":54321}", callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
_authenticationMock.Verify(m => m.AddHeader(It.IsAny<HttpClient>()), Times.Once);
_clientOptionsMock.Verify(o => o.BaseUrl, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Timeout, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.MaxRetries, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.DefaultHeaders, Times.Once);
_clientOptionsMock.Verify(o => o.DefaultQueryParams, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.AllowRedirects, Times.Once);
_clientOptionsMock.Verify(o => o.UseProxy, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Proxy, Times.Once);
VerifyNoOtherCalls();
}
[TestMethod]
[ExpectedException(typeof(JsonReaderException))]
public async Task ShouldThrowExceptionOnInvalidResponse()
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("This is a bad text :p", Encoding.UTF8, MediaTypeNames.Text.Plain),
});
var client = GetClient();
// Act
await client.PostAsync<TestClass, TestClass>("some-path", _request);
}
[TestMethod]
public async Task ShouldOnlySerializeNonNullValues()
{
// Arrange
_request.Str = null;
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("This is an awesome text ;-)", Encoding.UTF8, MediaTypeNames.Text.Plain),
});
var client = GetClient();
// Act
var response = await client.PostAsync<string, TestClass>("path", _request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNull(response.Errors);
Assert.IsNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual("This is an awesome text ;-)", response.Result);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Post, callback.Method);
Assert.AreEqual("https://localhost/api/v4/path", callback.Url);
Assert.AreEqual(@"{""integer"":54321}", callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
_authenticationMock.Verify(m => m.AddHeader(It.IsAny<HttpClient>()), Times.Once);
VerifyDefaults();
VerifyNoOtherCalls();
}
private void VerifyDefaults()
{
_authenticationMock.Verify(m => m.AddHeader(It.IsAny<HttpClient>()), Times.Once);
_clientOptionsMock.Verify(o => o.BaseUrl, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Timeout, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.MaxRetries, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.DefaultHeaders, Times.Once);
_clientOptionsMock.Verify(o => o.DefaultQueryParams, Times.Once);
_clientOptionsMock.Verify(o => o.AllowRedirects, Times.Once);
_clientOptionsMock.Verify(o => o.UseProxy, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Proxy, Times.Once);
}
private void VerifyNoOtherCalls()
{
_httpHandlerMock.Mock.VerifyNoOtherCalls();
_authenticationMock.VerifyNoOtherCalls();
_clientOptionsMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
var httpClient = new HttpClient(_httpHandlerMock.Mock.Object)
{
Timeout = _clientOptionsMock.Object.Timeout,
BaseAddress = new Uri(BaseUrl),
};
httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("AMWD.CloudflareClient", "1.0.0"));
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (_clientOptionsMock.Object.DefaultHeaders.Count > 0)
{
foreach (var headerKvp in _clientOptionsMock.Object.DefaultHeaders)
httpClient.DefaultRequestHeaders.Add(headerKvp.Key, headerKvp.Value);
}
_authenticationMock.Object.AddHeader(httpClient);
_authenticationMock.Invocations.Clear();
_clientOptionsMock.Invocations.Clear();
var client = new CloudflareClient(_authenticationMock.Object, _clientOptionsMock.Object);
var httpClientField = client.GetType()
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
(httpClientField.GetValue(client) as HttpClient).Dispose();
httpClientField.SetValue(client, httpClient);
return client;
}
private class TestClass
{
[JsonProperty("string")]
public string Str { get; set; }
[JsonProperty("integer")]
public int Int { get; set; }
}
private class TestFilter : IQueryParameterFilter
{
public IDictionary<string, string> GetQueryParameters()
{
return new Dictionary<string, string>
{
{ "test", "filter-text" }
};
}
}
}
}

View File

@@ -0,0 +1,423 @@
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Reflection;
using System.Security.Authentication;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using Moq;
using Moq.Protected;
namespace Cloudflare.Core.Tests.CloudflareClientTests
{
[TestClass]
public class PutAsyncTest
{
private const string BaseUrl = "https://localhost/api/v4/";
private HttpMessageHandlerMock _httpHandlerMock;
private Mock<ClientOptions> _clientOptionsMock;
private Mock<IAuthentication> _authenticationMock;
private TestClass _request;
[TestInitialize]
public void Initialize()
{
_httpHandlerMock = new HttpMessageHandlerMock();
_authenticationMock = new Mock<IAuthentication>();
_clientOptionsMock = new Mock<ClientOptions>();
_authenticationMock
.Setup(a => a.AddHeader(It.IsAny<HttpClient>()))
.Callback<HttpClient>(c => c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Some-API-Token"));
_clientOptionsMock.Setup(o => o.BaseUrl).Returns(BaseUrl);
_clientOptionsMock.Setup(o => o.Timeout).Returns(TimeSpan.FromSeconds(60));
_clientOptionsMock.Setup(o => o.MaxRetries).Returns(2);
_clientOptionsMock.Setup(o => o.DefaultHeaders).Returns(new Dictionary<string, string>());
_clientOptionsMock.Setup(o => o.DefaultQueryParams).Returns(new Dictionary<string, string>());
_clientOptionsMock.Setup(o => o.AllowRedirects).Returns(false);
_clientOptionsMock.Setup(o => o.UseProxy).Returns(false);
_request = new TestClass
{
Int = 54321,
Str = "Happy Testing!"
};
}
[TestMethod]
[ExpectedException(typeof(ObjectDisposedException))]
public async Task ShouldThrowDisposed()
{
// Arrange
var client = GetClient() as CloudflareClient;
client.Dispose();
// Act
await client.PutAsync<object, object>("test", _request);
// Assert - ObjectDisposedException
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public async Task ShouldThrowArgumentNullOnRequestPath(string path)
{
// Arrange
var client = GetClient();
// Act
await client.PutAsync<object, object>(path, _request);
// Assert - ArgumentNullException
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public async Task ShouldThrowArgumentOnRequestPath()
{
// Arrange
var client = GetClient();
// Act
await client.PutAsync<object, object>("foo?bar=baz", _request);
// Assert - ArgumentException
}
[TestMethod]
public async Task ShouldPut()
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(@"{""success"": true, ""errors"": [], ""messages"": [], ""result"": { ""string"": ""some-string"", ""integer"": 123 }}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
// Act
var response = await client.PutAsync<TestClass, TestClass>("test", _request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNotNull(response.Errors);
Assert.IsNotNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual(0, response.Errors.Count);
Assert.AreEqual(0, response.Messages.Count);
Assert.IsNotNull(response.Result);
Assert.AreEqual("some-string", response.Result.Str);
Assert.AreEqual(123, response.Result.Int);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Put, callback.Method);
Assert.AreEqual("https://localhost/api/v4/test", callback.Url);
Assert.AreEqual(@"{""string"":""Happy Testing!"",""integer"":54321}", callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
VerifyDefaults();
VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldPutHttpContentDirectly()
{
// Arrange
var stringContent = new StringContent(@"{""test"":""HERE ?""}", Encoding.UTF8, "application/json");
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(@"{""success"": true, ""errors"": [], ""messages"": [], ""result"": { ""string"": ""some-string"", ""integer"": 123 }}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
// Act
var response = await client.PutAsync<TestClass, StringContent>("test", stringContent);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNotNull(response.Errors);
Assert.IsNotNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual(0, response.Errors.Count);
Assert.AreEqual(0, response.Messages.Count);
Assert.IsNotNull(response.Result);
Assert.AreEqual("some-string", response.Result.Str);
Assert.AreEqual(123, response.Result.Int);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Put, callback.Method);
Assert.AreEqual("https://localhost/api/v4/test", callback.Url);
Assert.AreEqual(@"{""test"":""HERE ?""}", callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
VerifyDefaults();
VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldPutWithoutContent()
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(@"{""success"": true, ""errors"": [], ""messages"": [], ""result"": { ""string"": ""some-string"", ""integer"": 123 }}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
// Act
var response = await client.PutAsync<TestClass, object>("putput", null);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNotNull(response.Errors);
Assert.IsNotNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual(0, response.Errors.Count);
Assert.AreEqual(0, response.Messages.Count);
Assert.IsNotNull(response.Result);
Assert.AreEqual("some-string", response.Result.Str);
Assert.AreEqual(123, response.Result.Int);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Put, callback.Method);
Assert.AreEqual("https://localhost/api/v4/putput", callback.Url);
Assert.IsNull(callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
}
[DataTestMethod]
[DataRow(HttpStatusCode.Unauthorized)]
[DataRow(HttpStatusCode.Forbidden)]
public async Task ShouldThrowAuthenticationExceptionOnStatusCode(HttpStatusCode statusCode)
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = statusCode,
Content = new StringContent(@"{""success"": false, ""errors"": [{ ""code"": ""4711"", ""message"": ""foo & baz."" }, { ""code"": ""4712"", ""message"": ""Happy Error!"" }], ""messages"": []}", Encoding.UTF8, MediaTypeNames.Application.Json),
});
var client = GetClient();
try
{
// Act
await client.PutAsync<object, object>("foo", _request);
Assert.Fail();
}
catch (AuthenticationException ex)
{
// Assert
Assert.IsNull(ex.InnerException);
Assert.AreEqual($"4711: foo & baz.{Environment.NewLine}4712: Happy Error!", ex.Message);
}
}
[TestMethod]
public async Task ShouldReturnPlainText()
{
// Arrange
_clientOptionsMock.Setup(o => o.DefaultQueryParams).Returns(new Dictionary<string, string> { { "bar", "08/15" } });
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("This is an awesome text ;-)", Encoding.UTF8, MediaTypeNames.Text.Plain),
});
var client = GetClient();
// Act
var response = await client.PutAsync<string, TestClass>("some-awesome-path", _request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.IsNull(response.Errors);
Assert.IsNull(response.Messages);
Assert.IsNull(response.ResultInfo);
Assert.AreEqual("This is an awesome text ;-)", response.Result);
Assert.AreEqual(1, _httpHandlerMock.Callbacks.Count);
var callback = _httpHandlerMock.Callbacks.First();
Assert.AreEqual(HttpMethod.Put, callback.Method);
Assert.AreEqual("https://localhost/api/v4/some-awesome-path?bar=08%2F15", callback.Url);
Assert.AreEqual(@"{""string"":""Happy Testing!"",""integer"":54321}", callback.Content);
Assert.AreEqual(3, callback.Headers.Count);
Assert.IsTrue(callback.Headers.ContainsKey("Accept"));
Assert.IsTrue(callback.Headers.ContainsKey("Authorization"));
Assert.IsTrue(callback.Headers.ContainsKey("User-Agent"));
Assert.AreEqual("application/json", callback.Headers["Accept"]);
Assert.AreEqual("Bearer Some-API-Token", callback.Headers["Authorization"]);
Assert.AreEqual("AMWD.CloudflareClient/1.0.0", callback.Headers["User-Agent"]);
_httpHandlerMock.Mock.Protected().Verify("SendAsync", Times.Once(), ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
_authenticationMock.Verify(m => m.AddHeader(It.IsAny<HttpClient>()), Times.Once);
_clientOptionsMock.Verify(o => o.BaseUrl, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Timeout, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.MaxRetries, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.DefaultHeaders, Times.Once);
_clientOptionsMock.Verify(o => o.DefaultQueryParams, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.AllowRedirects, Times.Once);
_clientOptionsMock.Verify(o => o.UseProxy, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Proxy, Times.Once);
VerifyNoOtherCalls();
}
[TestMethod]
[ExpectedException(typeof(JsonReaderException))]
public async Task ShouldThrowExceptionOnInvalidResponse()
{
// Arrange
_httpHandlerMock.Responses.Enqueue(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("This is a bad text :p", Encoding.UTF8, MediaTypeNames.Text.Plain),
});
var client = GetClient();
// Act
await client.PutAsync<TestClass, TestClass>("some-path", _request);
}
private void VerifyDefaults()
{
_authenticationMock.Verify(m => m.AddHeader(It.IsAny<HttpClient>()), Times.Once);
_clientOptionsMock.Verify(o => o.BaseUrl, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Timeout, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.MaxRetries, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.DefaultHeaders, Times.Once);
_clientOptionsMock.Verify(o => o.DefaultQueryParams, Times.Once);
_clientOptionsMock.Verify(o => o.AllowRedirects, Times.Once);
_clientOptionsMock.Verify(o => o.UseProxy, Times.Exactly(2));
_clientOptionsMock.Verify(o => o.Proxy, Times.Once);
}
private void VerifyNoOtherCalls()
{
_httpHandlerMock.Mock.VerifyNoOtherCalls();
_authenticationMock.VerifyNoOtherCalls();
_clientOptionsMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
var httpClient = new HttpClient(_httpHandlerMock.Mock.Object)
{
Timeout = _clientOptionsMock.Object.Timeout,
BaseAddress = new Uri(BaseUrl),
};
httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("AMWD.CloudflareClient", "1.0.0"));
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (_clientOptionsMock.Object.DefaultHeaders.Count > 0)
{
foreach (var headerKvp in _clientOptionsMock.Object.DefaultHeaders)
httpClient.DefaultRequestHeaders.Add(headerKvp.Key, headerKvp.Value);
}
_authenticationMock.Object.AddHeader(httpClient);
_authenticationMock.Invocations.Clear();
_clientOptionsMock.Invocations.Clear();
var client = new CloudflareClient(_authenticationMock.Object, _clientOptionsMock.Object);
var httpClientField = client.GetType()
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
(httpClientField.GetValue(client) as HttpClient).Dispose();
httpClientField.SetValue(client, httpClient);
return client;
}
private class TestClass
{
[JsonProperty("string")]
public string Str { get; set; }
[JsonProperty("integer")]
public int Int { get; set; }
}
private class TestFilter : IQueryParameterFilter
{
public IDictionary<string, string> GetQueryParameters()
{
return new Dictionary<string, string>
{
{ "test", "filter-text" }
};
}
}
}
}

View File

@@ -0,0 +1,64 @@
using System.Runtime.Serialization;
using AMWD.Net.Api.Cloudflare;
namespace Cloudflare.Core.Tests.Extensions
{
[TestClass]
public class EnumExtensionsTest
{
[TestMethod]
public void ShouldReturnEnumMemberValue()
{
// Arrange
var enumValue = EnumWithAttribute.One;
// Act
string val = enumValue.GetEnumMemberValue();
// Assert
Assert.AreEqual("eins", val);
}
[TestMethod]
public void ShouldReturnStringMissingAttribute()
{
// Arrange
var enumValue = EnumWithoutAttribute.Two;
// Act
string val = enumValue.GetEnumMemberValue();
// Assert
Assert.AreEqual("Two", val);
}
[TestMethod]
public void ShouldReturnString()
{
// Arrange
EnumWithAttribute enumValue = 0;
// Act
string val = enumValue.GetEnumMemberValue();
// Assert
Assert.AreEqual("0", val);
}
public enum EnumWithAttribute
{
[EnumMember(Value = "eins")]
One = 1,
[EnumMember(Value = "zwei")]
Two = 2,
}
public enum EnumWithoutAttribute
{
One = 1,
Two = 2,
}
}
}

View File

@@ -0,0 +1,172 @@
using System;
using AMWD.Net.Api.Cloudflare;
namespace Cloudflare.Tests.Extensions
{
[TestClass]
public class StringExtensionsTest
{
[TestMethod]
public void ShouldValidateId()
{
// Arrange
string id = "023e105f4ecef8ad9ca31a8372d0c353";
// Act
id.ValidateCloudflareId();
// Assert - no exception thrown
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowArgumentNullExceptionForValidateId(string name)
{
// Arrange
// Act
name.ValidateCloudflareId();
// Assert - ArgumentNullException
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void ShouldThrowArgumentOutOfRangeExceptionForValidateId()
{
// Arrange
string id = new('a', 33);
// Act
id.ValidateCloudflareId();
// Assert - ArgumentException
}
[DataTestMethod]
[DataRow("023e105f4ecef8ad9ca31a8372d0c35")]
[DataRow("023e105f4ecef8ad9ca31a8372d0C353")]
[DataRow("023e105f4ecef8ad9ca31a8372d0y353")]
[ExpectedException(typeof(ArgumentException))]
public void ShouldThrowArgumentExceptionForValidateId(string id)
{
// Arrange
// Act
id.ValidateCloudflareId();
// Assert - ArgumentException
}
[TestMethod]
public void ShouldValidateName()
{
// Arrange
string name = "Example Account Name";
// Act
name.ValidateCloudflareName();
// Assert - no exception thrown
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowArgumentNullExceptionForValidateName(string name)
{
// Arrange
// Act
name.ValidateCloudflareName();
// Assert - ArgumentNullException
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void ShouldThrowArgumentOutOfRangeExceptionForValidateName()
{
// Arrange
string name = new('a', 254);
// Act
name.ValidateCloudflareName();
// Assert - ArgumentException
}
[TestMethod]
public void ShouldValidateEmail()
{
// Arrange
string email = "test@example.com";
// Act
email.ValidateCloudflareEmailAddress();
// Assert - no exception thrown
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public void ShouldThrowArgumentNullExceptionForValidateEmail(string email)
{
// Arrange
// Act
email.ValidateCloudflareEmailAddress();
// Assert - ArgumentNullException
}
[DataTestMethod]
[DataRow("test")]
[DataRow("test@example")]
[DataRow("example.com")]
[ExpectedException(typeof(ArgumentException))]
public void ShouldThrowArgumentExceptionForValidateEmail(string email)
{
// Arrange
// Act
email.ValidateCloudflareEmailAddress();
// Assert - ArgumentException
}
[DataTestMethod]
[DataRow(null)]
[DataRow("SomeExampleString")]
public void ShouldValidateLength(string str)
{
// Arrange
// Act
str.ValidateLength(30, nameof(str));
// Assert - no exception thrown
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void ShouldThrowArgumentExceptionForValidateLength()
{
// Arrange
string str = "SomeExampleString";
// Act
str.ValidateLength(10, nameof(str));
// Assert - ArgumentException
}
}
}

View File

@@ -0,0 +1,52 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Moq;
using Moq.Protected;
namespace Cloudflare.Core.Tests
{
internal class HttpMessageHandlerMock
{
public HttpMessageHandlerMock()
{
Mock = new();
Mock.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.Callback<HttpRequestMessage, CancellationToken>(async (request, ct) =>
{
var callback = new HttpMessageRequestCallback
{
Method = request.Method,
Url = request.RequestUri.ToString(),
Headers = request.Headers.ToDictionary(h => h.Key, h => h.Value.First()),
};
if (request.Content != null)
callback.Content = await request.Content.ReadAsStringAsync();
Callbacks.Add(callback);
})
.ReturnsAsync(() => Responses.Dequeue());
}
public List<HttpMessageRequestCallback> Callbacks { get; } = [];
public Queue<HttpResponseMessage> Responses { get; } = new();
public Mock<HttpClientHandler> Mock { get; }
}
internal class HttpMessageRequestCallback
{
public HttpMethod Method { get; set; }
public string Url { get; set; }
public Dictionary<string, string> Headers { get; set; }
public string Content { get; set; }
}
}

View File

@@ -0,0 +1,30 @@
<Project>
<PropertyGroup>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<CollectCoverage>true</CollectCoverage>
<CoverletOutputFormat>Cobertura</CoverletOutputFormat>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="MSTest.TestAdapter" Version="3.9.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.9.1" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\src\Cloudflare\Cloudflare.csproj" />
</ItemGroup>
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)\..'))" />
</Project>

View File

@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\src\Extensions\Cloudflare.Zones\Cloudflare.Zones.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,81 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
using Newtonsoft.Json.Linq;
namespace Cloudflare.Zones.Tests.RegistrarExtensions
{
[TestClass]
public class GetDomainTest
{
private const string AccountId = "023e105f4ecef8ad9ca31a8372d0c353";
private const string DomainName = "example.com";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<JToken> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<JToken>();
}
[TestMethod]
public async Task ShouldGetRegistrarDomain()
{
// Arrange
var client = GetClient();
// Act
var result = await client.GetDomain(AccountId, DomainName);
// Assert
Assert.AreEqual(_response, result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/accounts/{AccountId}/registrar/domains/{DomainName}", callback.RequestPath);
Assert.IsNull(callback.QueryFilter);
_clientMock.Verify(m => m.GetAsync<JToken>($"/accounts/{AccountId}/registrar/domains/{DomainName}", null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public async Task ShouldThrowArgumentNullExceptionOnDomainName(string domainName)
{
// Arrange
var client = GetClient();
// Act
var result = await client.GetDomain(AccountId, domainName);
// Assert - ArgumentNullException
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.GetAsync<JToken>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,62 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.RegistrarExtensions
{
[TestClass]
public class ListDomainsTest
{
private const string AccountId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<IReadOnlyCollection<Domain>> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<IReadOnlyCollection<Domain>>();
}
[TestMethod]
public async Task ShouldListRegistrarDomains()
{
// Arrange
var client = GetClient();
// Act
var result = await client.ListDomains(AccountId);
// Assert
Assert.AreEqual(_response, result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/accounts/{AccountId}/registrar/domains", callback.RequestPath);
Assert.IsNull(callback.QueryFilter);
_clientMock.Verify(m => m.GetAsync<IReadOnlyCollection<Domain>>($"/accounts/{AccountId}/registrar/domains", null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.GetAsync<IReadOnlyCollection<Domain>>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,95 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using AMWD.Net.Api.Cloudflare.Zones.Internals;
using Moq;
using Newtonsoft.Json.Linq;
namespace Cloudflare.Zones.Tests.RegistrarExtensions
{
[TestClass]
public class UpdateDomainTest
{
private const string AccountId = "023e105f4ecef8ad9ca31a8372d0c353";
private const string DomainName = "example.com";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<JToken> _response;
private List<(string RequestPath, InternalUpdateDomainRequest Request)> _callbacks;
private UpdateDomainRequest _request;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<JToken>();
_request = new UpdateDomainRequest(AccountId, DomainName)
{
AutoRenew = true,
Privacy = false
};
}
[TestMethod]
public async Task ShouldUpdateRegistrarDomain()
{
// Arrange
var client = GetClient();
// Act
var result = await client.UpdateDomain(_request);
// Assert
Assert.AreEqual(_response, result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/accounts/{AccountId}/registrar/domains/{DomainName}", callback.RequestPath);
Assert.IsNotNull(callback.Request);
Assert.AreEqual(_request.AutoRenew, callback.Request.AutoRenew);
Assert.AreEqual(_request.Locked, callback.Request.Locked);
Assert.AreEqual(_request.Privacy, callback.Request.Privacy);
_clientMock.Verify(m => m.PutAsync<JToken, InternalUpdateDomainRequest>($"/accounts/{AccountId}/registrar/domains/{DomainName}", It.IsAny<InternalUpdateDomainRequest>(), It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
[ExpectedException(typeof(ArgumentNullException))]
public async Task ShouldThrowArgumentNullExceptionOnDomainName(string domainName)
{
// Arrange
_request.DomainName = domainName;
var client = GetClient();
// Act
var result = await client.UpdateDomain(_request);
// Assert - ArgumentNullException
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.PutAsync<JToken, InternalUpdateDomainRequest>(It.IsAny<string>(), It.IsAny<InternalUpdateDomainRequest>(), It.IsAny<CancellationToken>()))
.Callback<string, InternalUpdateDomainRequest, CancellationToken>((requestPath, request, _) => _callbacks.Add((requestPath, request)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,148 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using AMWD.Net.Api.Cloudflare.Zones.Internals;
using Moq;
namespace Cloudflare.Zones.Tests.ZoneHoldsExtensions
{
[TestClass]
public class CreateZoneHoldTest
{
private readonly DateTime _date = new(2025, 10, 10, 20, 30, 40, 0, DateTimeKind.Utc);
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<ZoneHold> _response;
private List<(string RequestPath, object Request, IQueryParameterFilter QueryFilter)> _callbacks;
private CreateZoneHoldRequest _request;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<ZoneHold>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new ZoneHold
{
Hold = true,
HoldAfter = _date,
IncludeSubdomains = false
}
};
_request = new CreateZoneHoldRequest(ZoneId);
}
[TestMethod]
public async Task ShouldCreateZoneHold()
{
// Arrange
var client = GetClient();
// Act
var response = await client.CreateZoneHold(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/hold", callback.RequestPath);
Assert.IsNotNull(callback.QueryFilter);
Assert.IsInstanceOfType<InternalCreateZoneHoldFilter>(callback.QueryFilter);
Assert.IsNull(((InternalCreateZoneHoldFilter)callback.QueryFilter).IncludeSubdomains);
_clientMock.Verify(m => m.PostAsync<ZoneHold, object>($"/zones/{ZoneId}/hold", null, It.IsAny<InternalCreateZoneHoldFilter>(), It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldCreateZoneHoldWithSubdomains()
{
// Arrange
_request.IncludeSubdomains = true;
var client = GetClient();
// Act
var response = await client.CreateZoneHold(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/hold", callback.RequestPath);
Assert.IsNotNull(callback.QueryFilter);
Assert.IsInstanceOfType<InternalCreateZoneHoldFilter>(callback.QueryFilter);
Assert.IsTrue(((InternalCreateZoneHoldFilter)callback.QueryFilter).IncludeSubdomains);
_clientMock.Verify(m => m.PostAsync<ZoneHold, object>($"/zones/{ZoneId}/hold", null, It.IsAny<InternalCreateZoneHoldFilter>(), It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[TestMethod]
public void ShouldReturnEmptyDictionary()
{
// Arrange
var filter = new InternalCreateZoneHoldFilter();
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(0, dict.Count);
}
[DataTestMethod]
[DataRow(true)]
[DataRow(false)]
public void ShouldReturnQueryParameter(bool includeSubdomains)
{
// Arrange
var filter = new InternalCreateZoneHoldFilter { IncludeSubdomains = includeSubdomains };
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(1, dict.Count);
Assert.IsTrue(dict.ContainsKey("include_subdomains"));
Assert.AreEqual(includeSubdomains.ToString().ToLower(), dict["include_subdomains"]);
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.PostAsync<ZoneHold, object>(It.IsAny<string>(), It.IsAny<object>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, object, IQueryParameterFilter, CancellationToken>((requestPath, request, queryFilter, _) => _callbacks.Add((requestPath, request, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,80 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.ZoneHoldsExtensions
{
[TestClass]
public class GetZoneHoldTest
{
private readonly DateTime _date = new DateTime(2024, 10, 10, 20, 30, 40, 0, DateTimeKind.Utc);
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<ZoneHold> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<ZoneHold>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new ZoneHold
{
Hold = true,
HoldAfter = _date,
IncludeSubdomains = false
}
};
}
[TestMethod]
public async Task ShouldGetZoneHold()
{
// Arrange
var client = GetClient();
// Act
var response = await client.GetZoneHold(ZoneId);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/hold", callback.RequestPath);
Assert.IsNull(callback.QueryFilter);
_clientMock.Verify(m => m.GetAsync<ZoneHold>($"/zones/{ZoneId}/hold", null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.GetAsync<ZoneHold>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,147 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using AMWD.Net.Api.Cloudflare.Zones.Internals;
using Moq;
namespace Cloudflare.Zones.Tests.ZoneHoldsExtensions
{
[TestClass]
public class RemoveZoneHoldTest
{
// Local: Europe/Berlin (Germany) - [CEST +2] | CET +1
private readonly DateTime _date = new(2025, 10, 10, 20, 30, 40, 0, DateTimeKind.Unspecified);
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<ZoneHold> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
private RemoveZoneHoldRequest _request;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<ZoneHold>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new ZoneHold
{
Hold = true,
HoldAfter = _date,
IncludeSubdomains = true
}
};
_request = new RemoveZoneHoldRequest(ZoneId);
}
[TestMethod]
public async Task ShouldRemoveZoneHold()
{
// Arrange
var client = GetClient();
// Act
var response = await client.RemoveZoneHold(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/hold", callback.RequestPath);
Assert.IsNotNull(callback.QueryFilter);
Assert.IsInstanceOfType<InternalRemoveZoneHoldFilter>(callback.QueryFilter);
Assert.IsNull(((InternalRemoveZoneHoldFilter)callback.QueryFilter).HoldAfter);
_clientMock.Verify(m => m.DeleteAsync<ZoneHold>($"/zones/{ZoneId}/hold", It.IsAny<InternalRemoveZoneHoldFilter>(), It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldRemoveZoneHoldTemporarily()
{
// Arrange
_request.HoldAfter = _date;
var client = GetClient();
// Act
var response = await client.RemoveZoneHold(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/hold", callback.RequestPath);
Assert.IsNotNull(callback.QueryFilter);
Assert.IsInstanceOfType<InternalRemoveZoneHoldFilter>(callback.QueryFilter);
Assert.AreEqual(_date, ((InternalRemoveZoneHoldFilter)callback.QueryFilter).HoldAfter);
_clientMock.Verify(m => m.DeleteAsync<ZoneHold>($"/zones/{ZoneId}/hold", It.IsAny<InternalRemoveZoneHoldFilter>(), It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[TestMethod]
public void ShouldReturnEmptyDictionary()
{
// Arrange
var filter = new InternalRemoveZoneHoldFilter();
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(0, dict.Count);
}
[TestMethod]
public void ShouldReturnQueryParameter()
{
// Arrange
var filter = new InternalRemoveZoneHoldFilter { HoldAfter = _date };
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(1, dict.Count);
Assert.IsTrue(dict.ContainsKey("hold_after"));
Assert.AreEqual("2025-10-10T18:30:40Z", dict["hold_after"]);
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.DeleteAsync<ZoneHold>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,89 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using AMWD.Net.Api.Cloudflare.Zones.Internals;
using Moq;
namespace Cloudflare.Zones.Tests.ZoneHoldsExtensions
{
[TestClass]
public class UpdateZoneHoldTest
{
private readonly DateTime _date = new DateTime(2024, 10, 10, 20, 30, 40, 0, DateTimeKind.Utc);
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<ZoneHold> _response;
private List<(string RequestPath, InternalUpdateZoneHoldRequest Request)> _callbacks;
private UpdateZoneHoldRequest _request;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<ZoneHold>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new ZoneHold
{
Hold = true,
HoldAfter = _date,
IncludeSubdomains = false
}
};
_request = new UpdateZoneHoldRequest(ZoneId)
{
HoldAfter = _date,
IncludeSubdomains = true
};
}
[TestMethod]
public async Task ShouldUpdateZoneHold()
{
// Arrange
var client = GetClient();
// Act
var response = await client.UpdateZoneHold(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/hold", callback.RequestPath);
Assert.IsNotNull(callback.Request);
Assert.AreEqual(_date, callback.Request.HoldAfter);
Assert.IsTrue(callback.Request.IncludeSubdomains);
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.PatchAsync<ZoneHold, InternalUpdateZoneHoldRequest>(It.IsAny<string>(), It.IsAny<InternalUpdateZoneHoldRequest>(), It.IsAny<CancellationToken>()))
.Callback<string, InternalUpdateZoneHoldRequest, CancellationToken>((requestPath, request, _) => _callbacks.Add((requestPath, request)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,75 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.ZonePlansExtensions
{
[TestClass]
public class AvailablePlanDetailsTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private const string PlanId = "023e105f4ecef8ad9ca31a8372d0c354";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<AvailableRatePlan> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<AvailableRatePlan>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new AvailableRatePlan()
};
}
[TestMethod]
public async Task ShouldReturnAvailablePlan()
{
// Arrange
var client = GetClient();
// Act
var response = await client.AvailablePlanDetails(ZoneId, PlanId);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/available_plans/{PlanId}", callback.RequestPath);
Assert.IsNull(callback.QueryFilter);
_clientMock.Verify(m => m.GetAsync<AvailableRatePlan>($"/zones/{ZoneId}/available_plans/{PlanId}", null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.GetAsync<AvailableRatePlan>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,74 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.ZonePlansExtensions
{
[TestClass]
public class ListAvailablePlansTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<IReadOnlyCollection<AvailableRatePlan>> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<IReadOnlyCollection<AvailableRatePlan>>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = []
};
}
[TestMethod]
public async Task ShouldReturnAvailablePlan()
{
// Arrange
var client = GetClient();
// Act
var response = await client.ListAvailablePlans(ZoneId);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/available_plans", callback.RequestPath);
Assert.IsNull(callback.QueryFilter);
_clientMock.Verify(m => m.GetAsync<IReadOnlyCollection<AvailableRatePlan>>($"/zones/{ZoneId}/available_plans", null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.GetAsync<IReadOnlyCollection<AvailableRatePlan>>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,74 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.ZonePlansExtensions
{
[TestClass]
public class ListAvailableRatePlansTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<RatePlanGetResponse> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<RatePlanGetResponse>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new()
};
}
[TestMethod]
public async Task ShouldReturnAvailablePlans()
{
// Arrange
var client = GetClient();
// Act
var response = await client.ListAvailableRatePlans(ZoneId);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/available_rate_plans", callback.RequestPath);
Assert.IsNull(callback.QueryFilter);
_clientMock.Verify(m => m.GetAsync<RatePlanGetResponse>($"/zones/{ZoneId}/available_rate_plans", null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.GetAsync<RatePlanGetResponse>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,91 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.ZoneSettingsExtensions
{
[TestClass]
public class EditMultipleZoneSettingsTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<IReadOnlyCollection<ZoneSettingBase>> _response;
private List<(string RequestPath, IReadOnlyCollection<ZoneSettingBase> Request)> _callbacks;
private EditMultipleZoneSettingsRequest _request;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<IReadOnlyCollection<ZoneSettingBase>>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = [
new SSL { Value = SslMode.Flexible },
new WebP { Value = OnOffState.Off }
]
};
_request = new EditMultipleZoneSettingsRequest(ZoneId)
{
Settings = [
new SSL { Value = SslMode.Strict },
new WebP { Value = OnOffState.On }
]
};
}
[TestMethod]
public async Task ShouldEditMultipleZoneSettings()
{
// Arrange
var client = GetClient();
// Act
#pragma warning disable CS0618
var response = await client.EditMultipleZoneSettings(_request);
#pragma warning restore CS0618
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/settings", callback.RequestPath);
Assert.IsNotNull(callback.Request);
Assert.AreEqual(2, callback.Request.Count);
Assert.IsInstanceOfType<SSL>(callback.Request.First());
Assert.IsInstanceOfType<WebP>(callback.Request.Last());
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.PatchAsync<IReadOnlyCollection<ZoneSettingBase>, IReadOnlyCollection<ZoneSettingBase>>(It.IsAny<string>(), It.IsAny<IReadOnlyCollection<ZoneSettingBase>>(), It.IsAny<CancellationToken>()))
.Callback<string, IReadOnlyCollection<ZoneSettingBase>, CancellationToken>((requestPath, request, _) => _callbacks.Add((requestPath, request)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,127 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
using Newtonsoft.Json.Linq;
namespace Cloudflare.Zones.Tests.ZoneSettingsExtensions
{
[TestClass]
public class EditZoneSettingTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<SSL> _response;
private List<(string RequestPath, JObject Request)> _callbacks;
private EditZoneSettingRequest<SSL> _request;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<SSL>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new SSL { Value = SslMode.Flexible }
};
_request = new EditZoneSettingRequest<SSL>(ZoneId, null)
{
Setting = new SSL { Value = SslMode.OriginPull }
};
}
[TestMethod]
public async Task ShouldEditZoneSetting()
{
// Arrange
var client = GetClient();
// Act
var response = await client.EditZoneSetting(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/settings/ssl", callback.RequestPath);
Assert.IsNotNull(callback.Request);
Assert.AreEqual("origin_pull", callback.Request["value"]);
Assert.IsFalse(callback.Request.ContainsKey("enabled"));
}
[DataTestMethod]
[DataRow(true)]
[DataRow(false)]
public async Task ShouldEditEnabledState(bool enabled)
{
// Arrange
_request.Enabled = enabled;
var client = GetClient();
// Act
var response = await client.EditZoneSetting(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/settings/ssl", callback.RequestPath);
Assert.IsNotNull(callback.Request);
Assert.AreEqual(enabled, callback.Request["enabled"]);
Assert.IsFalse(callback.Request.ContainsKey("value"));
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public async Task ShouldThrowArgumentException()
{
// Arrange
var request = new EditZoneSettingRequest<TestSetting>(ZoneId, new TestSetting());
var client = GetClient();
// Act
var response = await client.EditZoneSetting(request);
// Assert - ArgumentException
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.PatchAsync<SSL, JObject>(It.IsAny<string>(), It.IsAny<JObject>(), It.IsAny<CancellationToken>()))
.Callback<string, JObject, CancellationToken>((requestPath, request, _) => _callbacks.Add((requestPath, request)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
public class TestSetting : ZoneSettingBase
{
}
}
}

View File

@@ -0,0 +1,79 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.ZoneSettingsExtensions
{
[TestClass]
public class GetAllZoneSettingsTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<IReadOnlyCollection<ZoneSettingBase>> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<IReadOnlyCollection<ZoneSettingBase>>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = [
new SSL { Value = SslMode.Flexible },
new WebP { Value = OnOffState.Off }
]
};
}
[TestMethod]
public async Task ShouldReturnZoneSetting()
{
// Arrange
var client = GetClient();
// Act
#pragma warning disable CS0618
var response = await client.GetAllZoneSettings(ZoneId);
#pragma warning restore CS0618
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/settings", callback.RequestPath);
Assert.IsNull(callback.QueryFilter);
_clientMock.Verify(m => m.GetAsync<IReadOnlyCollection<ZoneSettingBase>>($"/zones/{ZoneId}/settings", null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.GetAsync<IReadOnlyCollection<ZoneSettingBase>>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,91 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.ZoneSettingsExtensions
{
[TestClass]
public class GetZoneSettingTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<SSL> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<SSL>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new SSL { Value = SslMode.Flexible }
};
}
[TestMethod]
public async Task ShouldReturnZoneSetting()
{
// Arrange
var client = GetClient();
// Act
var response = await client.GetZoneSetting<SSL>(ZoneId);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/settings/ssl", callback.RequestPath);
Assert.IsNull(callback.QueryFilter);
_clientMock.Verify(m => m.GetAsync<SSL>($"/zones/{ZoneId}/settings/ssl", null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public async Task ShouldThrowArgumentException()
{
// Arrange
var client = GetClient();
// Act
var response = await client.GetZoneSetting<TestSetting>(ZoneId);
// Assert - ArgumentException
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.GetAsync<SSL>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
public class TestSetting : ZoneSettingBase
{
}
}
}

View File

@@ -0,0 +1,90 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using AMWD.Net.Api.Cloudflare.Zones.Internals;
using Moq;
namespace Cloudflare.Zones.Tests.ZoneSubscriptionsExtensions
{
[TestClass]
public class CreateZoneSubscriptionTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<Subscription> _response;
private List<(string RequestPath, InternalCreateZoneSubscriptionRequest Request)> _callbacks;
private CreateZoneSubscriptionRequest _request;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<Subscription>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new Subscription()
};
_request = new CreateZoneSubscriptionRequest(ZoneId)
{
Frequency = RenewFrequency.Quarterly,
RatePlan = new RatePlan
{
Id = RatePlanId.Business,
PublicName = "Business Plan"
}
};
}
[TestMethod]
public async Task ShouldCreateZoneSubscription()
{
// Arrange
var client = GetClient();
// Act
var response = await client.CreateZoneSubscription(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/subscription", callback.RequestPath);
Assert.IsNotNull(callback.Request);
Assert.AreEqual(_request.Frequency, callback.Request.Frequency);
Assert.AreEqual(_request.RatePlan, callback.Request.RatePlan);
_clientMock.Verify(m => m.PostAsync<Subscription, InternalCreateZoneSubscriptionRequest>($"/zones/{ZoneId}/subscription", It.IsAny<InternalCreateZoneSubscriptionRequest>(), null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.PostAsync<Subscription, InternalCreateZoneSubscriptionRequest>(It.IsAny<string>(), It.IsAny<InternalCreateZoneSubscriptionRequest>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, InternalCreateZoneSubscriptionRequest, IQueryParameterFilter, CancellationToken>((requestPath, request, _, _) => _callbacks.Add((requestPath, request)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,90 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using AMWD.Net.Api.Cloudflare.Zones.Internals;
using Moq;
namespace Cloudflare.Zones.Tests.ZoneSubscriptionsExtensions
{
[TestClass]
public class UpdateZoneSubscriptionTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<Subscription> _response;
private List<(string RequestPath, InternalUpdateZoneSubscriptionRequest Request)> _callbacks;
private UpdateZoneSubscriptionRequest _request;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<Subscription>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new Subscription()
};
_request = new UpdateZoneSubscriptionRequest(ZoneId)
{
Frequency = RenewFrequency.Quarterly,
RatePlan = new RatePlan
{
Id = RatePlanId.Business,
PublicName = "Business Plan"
}
};
}
[TestMethod]
public async Task ShouldUpdateZoneSubscription()
{
// Arrange
var client = GetClient();
// Act
var response = await client.UpdateZoneSubscription(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/subscription", callback.RequestPath);
Assert.IsNotNull(callback.Request);
Assert.AreEqual(_request.Frequency, callback.Request.Frequency);
Assert.AreEqual(_request.RatePlan, callback.Request.RatePlan);
_clientMock.Verify(m => m.PutAsync<Subscription, InternalUpdateZoneSubscriptionRequest>($"/zones/{ZoneId}/subscription", It.IsAny<InternalUpdateZoneSubscriptionRequest>(), It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.PutAsync<Subscription, InternalUpdateZoneSubscriptionRequest>(It.IsAny<string>(), It.IsAny<InternalUpdateZoneSubscriptionRequest>(), It.IsAny<CancellationToken>()))
.Callback<string, InternalUpdateZoneSubscriptionRequest, CancellationToken>((requestPath, request, _) => _callbacks.Add((requestPath, request)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,74 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.ZoneSubscriptionsExtensions
{
[TestClass]
public class ZoneSubscriptionDetailsTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<Subscription> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<Subscription>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new Subscription()
};
}
[TestMethod]
public async Task ShouldGetZoneSubscriptionDetails()
{
// Arrange
var client = GetClient();
// Act
var response = await client.ZoneSubscriptionDetails(ZoneId);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/subscription", callback.RequestPath);
Assert.IsNull(callback.QueryFilter);
_clientMock.Verify(m => m.GetAsync<Subscription>($"/zones/{ZoneId}/subscription", null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.GetAsync<Subscription>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,153 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using AMWD.Net.Api.Cloudflare.Zones.Internals;
using Moq;
namespace Cloudflare.Zones.Tests.ZonesExtensions
{
[TestClass]
public class CreateZoneTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<Zone> _response;
private List<(string RequestPath, InternalCreateZoneRequest Request)> _callbacks;
private CreateZoneRequest _request;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<Zone>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new Zone(
ZoneId,
"example.com",
[
"bob.ns.cloudflare.com",
"lola.ns.cloudflare.com"
],
new ZoneAccount
{
Id = "023e105f4ecef8ad9ca31a8372d0c353",
Name = "Example Account Name"
},
new ZoneMeta
{
CdnOnly = true,
CustomCertificateQuota = 1,
DnsOnly = true,
FoundationDns = true,
PageRuleQuota = 100,
PhishingDetected = false,
Step = 2
},
new ZoneOwner
{
Id = "023e105f4ecef8ad9ca31a8372d0c353",
Name = "Example Org",
Type = "organization"
}
)
{
ActivatedOn = DateTime.Parse("2014-01-02T00:01:00.12345Z"),
CreatedOn = DateTime.Parse("2014-01-01T05:20:00.12345Z"),
DevelopmentMode = 7200,
ModifiedOn = DateTime.Parse("2014-01-01T05:20:00.12345Z"),
Name = "example.com",
OriginalDnsHost = "NameCheap",
OriginalNameServers =
[
"ns1.originaldnshost.com",
"ns2.originaldnshost.com"
],
OriginalRegistrar = "GoDaddy",
Paused = true,
Status = ZoneStatus.Initializing,
Type = ZoneType.Full,
VanityNameServers =
[
"ns1.example.com",
"ns2.example.com"
]
}
};
_request = new CreateZoneRequest("example.com")
{
Type = ZoneType.Full
};
}
[DataTestMethod]
[DataRow(null)]
[DataRow("023e105f4ecef8ad9ca31a8372d0c353")]
public async Task ShouldCreateZone(string accountId)
{
// Arrange
_request.AccountId = accountId;
var client = GetClient();
// Act
var response = await client.CreateZone(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual("/zones", callback.RequestPath);
Assert.IsNotNull(callback.Request);
Assert.AreEqual(_request.AccountId, callback.Request.Account.Id);
Assert.AreEqual(_request.Name, callback.Request.Name);
Assert.AreEqual(_request.Type, callback.Request.Type);
_clientMock.Verify(m => m.PostAsync<Zone, InternalCreateZoneRequest>("/zones", It.IsAny<InternalCreateZoneRequest>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public async Task ShouldThrowArgumentOutOfRangeExceptionOnInvalidType()
{
// Arrange
_request.Type = 0;
var client = GetClient();
// Act
await client.CreateZone(_request);
// Assert - ArgumentOutOfRangeException
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.PostAsync<Zone, InternalCreateZoneRequest>(It.IsAny<string>(), It.IsAny<InternalCreateZoneRequest>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, InternalCreateZoneRequest, IQueryParameterFilter, CancellationToken>((requestPath, request, _, _) => _callbacks.Add((requestPath, request)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,77 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.ZonesExtensions
{
[TestClass]
public class DeleteZoneTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<Identifier> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<Identifier>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new Identifier
{
Id = ZoneId
}
};
}
[TestMethod]
public async Task ShouldDeleteZone()
{
// Arrange
var client = GetClient();
// Act
var response = await client.DeleteZone(ZoneId);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}", callback.RequestPath);
Assert.IsNull(callback.QueryFilter);
_clientMock.Verify(m => m.DeleteAsync<Identifier>($"/zones/{ZoneId}", It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.DeleteAsync<Identifier>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,246 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using AMWD.Net.Api.Cloudflare.Zones.Internals;
using Moq;
namespace Cloudflare.Zones.Tests.ZonesExtensions
{
[TestClass]
public class EditZoneTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<Zone> _response;
private List<(string RequestPath, InternalEditZoneRequest Request)> _callbacks;
private EditZoneRequest _request;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<Zone>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new Zone(
ZoneId,
"example.com",
[
"bob.ns.cloudflare.com",
"lola.ns.cloudflare.com"
],
new ZoneAccount
{
Id = "023e105f4ecef8ad9ca31a8372d0c353",
Name = "Example Account Name"
},
new ZoneMeta
{
CdnOnly = true,
CustomCertificateQuota = 1,
DnsOnly = true,
FoundationDns = true,
PageRuleQuota = 100,
PhishingDetected = false,
Step = 2
},
new ZoneOwner
{
Id = "023e105f4ecef8ad9ca31a8372d0c353",
Name = "Example Org",
Type = "organization"
}
)
{
ActivatedOn = DateTime.Parse("2014-01-02T00:01:00.12345Z"),
CreatedOn = DateTime.Parse("2014-01-01T05:20:00.12345Z"),
DevelopmentMode = 7200,
ModifiedOn = DateTime.Parse("2014-01-01T05:20:00.12345Z"),
OriginalDnsHost = "NameCheap",
OriginalNameServers =
[
"ns1.originaldnshost.com",
"ns2.originaldnshost.com"
],
OriginalRegistrar = "GoDaddy",
Paused = true,
Status = ZoneStatus.Initializing,
Type = ZoneType.Full,
VanityNameServers =
[
"ns1.example.com",
"ns2.example.com"
]
}
};
_request = new EditZoneRequest(ZoneId)
{
Paused = true,
Type = ZoneType.Full,
VanityNameServers = ["ns1.example.org", "ns2.example.org"]
};
}
[TestMethod]
public async Task ShouldReturnModifiedZoneForPaused()
{
// Arrange
_request.Type = null;
_request.VanityNameServers = null;
var client = GetClient();
// Act
var response = await client.EditZone(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}", callback.RequestPath);
Assert.IsNotNull(callback.Request);
Assert.IsTrue(callback.Request.Paused);
Assert.IsNull(callback.Request.Type);
Assert.IsNull(callback.Request.VanityNameServers);
_clientMock.Verify(m => m.PatchAsync<Zone, InternalEditZoneRequest>($"/zones/{ZoneId}", It.IsAny<InternalEditZoneRequest>(), It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldReturnModifiedZoneForType()
{
// Arrange
_request.Paused = null;
_request.VanityNameServers = null;
var client = GetClient();
// Act
var response = await client.EditZone(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}", callback.RequestPath);
Assert.IsNotNull(callback.Request);
Assert.IsNull(callback.Request.Paused);
Assert.AreEqual(_request.Type.Value, callback.Request.Type.Value);
Assert.IsNull(callback.Request.VanityNameServers);
_clientMock.Verify(m => m.PatchAsync<Zone, InternalEditZoneRequest>($"/zones/{ZoneId}", It.IsAny<InternalEditZoneRequest>(), It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldReturnModifiedZoneForVanityNameServers()
{
// Arrange
_request.Paused = null;
_request.Type = null;
_request.VanityNameServers = [.. _request.VanityNameServers, ""];
var client = GetClient();
// Act
var response = await client.EditZone(_request);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}", callback.RequestPath);
Assert.IsNotNull(callback.Request);
Assert.IsNull(callback.Request.Paused);
Assert.IsNull(callback.Request.Type);
Assert.AreEqual(2, callback.Request.VanityNameServers.Count);
Assert.IsTrue(callback.Request.VanityNameServers.Contains("ns1.example.org"));
Assert.IsTrue(callback.Request.VanityNameServers.Contains("ns2.example.org"));
_clientMock.Verify(m => m.PatchAsync<Zone, InternalEditZoneRequest>($"/zones/{ZoneId}", It.IsAny<InternalEditZoneRequest>(), It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[TestMethod]
[ExpectedException(typeof(CloudflareException))]
public async Task ShouldThrowCloudflareExceptionOnMultiplePropertiesSet1()
{
// Arrange
_request.VanityNameServers = null;
var client = GetClient();
// Act
await client.EditZone(_request);
// Assert - CloudflareException
}
[TestMethod]
[ExpectedException(typeof(CloudflareException))]
public async Task ShouldThrowCloudflareExceptionOnMultiplePropertiesSet2()
{
// Arrange
_request.Paused = null;
var client = GetClient();
// Act
await client.EditZone(_request);
// Assert - CloudflareException
}
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public async Task ShouldThrowArgumentOutOfRangeExceptionForInvalidType()
{
// Arrange
_request.Paused = null;
_request.Type = 0;
_request.VanityNameServers = null;
var client = GetClient();
// Act
await client.EditZone(_request);
// Assert - ArgumentOutOfRangeException
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.PatchAsync<Zone, InternalEditZoneRequest>(It.IsAny<string>(), It.IsAny<InternalEditZoneRequest>(), It.IsAny<CancellationToken>()))
.Callback<string, InternalEditZoneRequest, CancellationToken>((requestPath, request, _) => _callbacks.Add((requestPath, request)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,385 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.ZonesExtensions
{
[TestClass]
public class ListZonesTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<IReadOnlyCollection<Zone>> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<IReadOnlyCollection<Zone>>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
ResultInfo = new PaginationInfo
{
Count = 1,
Page = 1,
PerPage = 20,
TotalCount = 2000
},
Result =
[
new Zone(
ZoneId,
"example.com",
[
"bob.ns.cloudflare.com",
"lola.ns.cloudflare.com"
],
new ZoneAccount
{
Id = "023e105f4ecef8ad9ca31a8372d0c353",
Name = "Example Account Name"
},
new ZoneMeta
{
CdnOnly = true,
CustomCertificateQuota = 1,
DnsOnly = true,
FoundationDns = true,
PageRuleQuota = 100,
PhishingDetected = false,
Step = 2
},
new ZoneOwner
{
Id = "023e105f4ecef8ad9ca31a8372d0c353",
Name = "Example Org",
Type = "organization"
}
)
{
ActivatedOn = DateTime.Parse("2014-01-02T00:01:00.12345Z"),
CreatedOn = DateTime.Parse("2014-01-01T05:20:00.12345Z"),
DevelopmentMode = 7200,
ModifiedOn = DateTime.Parse("2014-01-01T05:20:00.12345Z"),
OriginalDnsHost = "NameCheap",
OriginalNameServers =
[
"ns1.originaldnshost.com",
"ns2.originaldnshost.com"
],
OriginalRegistrar = "GoDaddy",
Paused = true,
Status = ZoneStatus.Initializing,
Type = ZoneType.Full,
VanityNameServers =
[
"ns1.example.com",
"ns2.example.com"
]
}
]
};
}
[TestMethod]
public async Task ShouldReturnListOfZones()
{
// Arrange
var client = GetClient();
// Act
var response = await client.ListZones();
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual("/zones", callback.RequestPath);
Assert.IsNull(callback.QueryFilter);
_clientMock.Verify(m => m.GetAsync<IReadOnlyCollection<Zone>>("/zones", null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldReturnListOfZonesWithFilter()
{
// Arrange
var filter = new ListZonesFilter
{
AccountId = "023e105f4ecef8ad9ca31a8372d0c353"
};
var client = GetClient();
// Act
var response = await client.ListZones(filter);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual("/zones", callback.RequestPath);
Assert.AreEqual(filter, callback.QueryFilter);
_clientMock.Verify(m => m.GetAsync<IReadOnlyCollection<Zone>>("/zones", filter, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
[TestMethod]
public void ShouldReturnEmptyParameterList()
{
// Arrange
var filter = new ListZonesFilter();
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(0, dict.Count);
}
[TestMethod]
public void ShouldReturnFullParameterList()
{
// Arrange
var filter = new ListZonesFilter
{
AccountId = "023e105f4ecef8ad9ca31a8372d0c353",
AccountName = "Example Account Name",
Match = ListZonesMatch.Any,
Name = "example.com",
PerPage = 13,
Page = 5,
OrderBy = ListZonesOrderBy.AccountName,
Direction = SortDirection.Descending,
Status = ZoneStatus.Active
};
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(9, dict.Count);
Assert.IsTrue(dict.ContainsKey("account.id"));
Assert.IsTrue(dict.ContainsKey("account.name"));
Assert.IsTrue(dict.ContainsKey("direction"));
Assert.IsTrue(dict.ContainsKey("match"));
Assert.IsTrue(dict.ContainsKey("name"));
Assert.IsTrue(dict.ContainsKey("order"));
Assert.IsTrue(dict.ContainsKey("page"));
Assert.IsTrue(dict.ContainsKey("per_page"));
Assert.IsTrue(dict.ContainsKey("status"));
Assert.AreEqual("023e105f4ecef8ad9ca31a8372d0c353", dict["account.id"]);
Assert.AreEqual("Example Account Name", dict["account.name"]);
Assert.AreEqual("desc", dict["direction"]);
Assert.AreEqual("any", dict["match"]);
Assert.AreEqual("example.com", dict["name"]);
Assert.AreEqual("account.name", dict["order"]);
Assert.AreEqual("5", dict["page"]);
Assert.AreEqual("13", dict["per_page"]);
Assert.AreEqual("active", dict["status"]);
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
public void ShouldNotAddAccountId(string id)
{
// Arrange
var filter = new ListZonesFilter
{
AccountId = id
};
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(0, dict.Count);
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
public void ShouldNotAddAccountName(string name)
{
// Arrange
var filter = new ListZonesFilter
{
AccountName = name
};
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(0, dict.Count);
}
[TestMethod]
public void ShouldNotAddDirection()
{
// Arrange
var filter = new ListZonesFilter
{
Direction = 0
};
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(0, dict.Count);
}
[TestMethod]
public void ShouldNotAddMatch()
{
// Arrange
var filter = new ListZonesFilter
{
Match = 0
};
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(0, dict.Count);
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
public void ShouldNotAddName(string name)
{
// Arrange
var filter = new ListZonesFilter
{
Name = name
};
// Act
var dict = new Dictionary<string, object>();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(0, dict.Count);
}
[TestMethod]
public void ShouldNotAddOrder()
{
// Arrange
var filter = new ListZonesFilter
{
OrderBy = 0
};
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(0, dict.Count);
}
[TestMethod]
public void ShouldNotAddPage()
{
// Arrange
var filter = new ListZonesFilter
{
Page = 0
};
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(0, dict.Count);
}
[DataTestMethod]
[DataRow(4)]
[DataRow(51)]
public void ShouldNotAddPerPage(int perPage)
{
// Arrange
var filter = new ListZonesFilter
{
PerPage = perPage
};
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(0, dict.Count);
}
[TestMethod]
public void ShouldNotAddStatus()
{
// Arrange
var filter = new ListZonesFilter
{
Status = 0
};
// Act
var dict = filter.GetQueryParameters();
// Assert
Assert.IsNotNull(dict);
Assert.AreEqual(0, dict.Count);
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.GetAsync<IReadOnlyCollection<Zone>>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,77 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.ZonesExtensions
{
[TestClass]
public class RerunActivationCheckTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<Identifier> _response;
private List<(string RequestPath, object Request)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<Identifier>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new Identifier
{
Id = ZoneId
}
};
}
[TestMethod]
public async Task ShouldRerunActivationCheck()
{
// Arrange
var client = GetClient();
// Act
var response = await client.RerunActivationCheck(ZoneId);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}/activation_check", callback.RequestPath);
Assert.IsNull(callback.Request);
_clientMock.Verify(m => m.PutAsync<Identifier, object>($"/zones/{ZoneId}/activation_check", null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.PutAsync<Identifier, object>(It.IsAny<string>(), It.IsAny<object>(), It.IsAny<CancellationToken>()))
.Callback<string, object, CancellationToken>((requestPath, request, _) => _callbacks.Add((requestPath, request)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}

View File

@@ -0,0 +1,123 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare;
using AMWD.Net.Api.Cloudflare.Zones;
using Moq;
namespace Cloudflare.Zones.Tests.ZonesExtensions
{
[TestClass]
public class ZoneDetailsTest
{
private const string ZoneId = "023e105f4ecef8ad9ca31a8372d0c353";
private Mock<ICloudflareClient> _clientMock;
private CloudflareResponse<Zone> _response;
private List<(string RequestPath, IQueryParameterFilter QueryFilter)> _callbacks;
[TestInitialize]
public void Initialize()
{
_callbacks = [];
_response = new CloudflareResponse<Zone>
{
Success = true,
Messages = [
new ResponseInfo(1000, "Message 1")
],
Errors = [
new ResponseInfo(1000, "Error 1")
],
Result = new Zone(
ZoneId,
"example.com",
[
"bob.ns.cloudflare.com",
"lola.ns.cloudflare.com"
],
new ZoneAccount
{
Id = "023e105f4ecef8ad9ca31a8372d0c353",
Name = "Example Account Name"
},
new ZoneMeta
{
CdnOnly = true,
CustomCertificateQuota = 1,
DnsOnly = true,
FoundationDns = true,
PageRuleQuota = 100,
PhishingDetected = false,
Step = 2
},
new ZoneOwner
{
Id = "023e105f4ecef8ad9ca31a8372d0c353",
Name = "Example Org",
Type = "organization"
}
)
{
ActivatedOn = DateTime.Parse("2014-01-02T00:01:00.12345Z"),
CreatedOn = DateTime.Parse("2014-01-01T05:20:00.12345Z"),
DevelopmentMode = 7200,
ModifiedOn = DateTime.Parse("2014-01-01T05:20:00.12345Z"),
OriginalDnsHost = "NameCheap",
OriginalNameServers =
[
"ns1.originaldnshost.com",
"ns2.originaldnshost.com"
],
OriginalRegistrar = "GoDaddy",
Paused = true,
Status = ZoneStatus.Initializing,
Type = ZoneType.Full,
VanityNameServers =
[
"ns1.example.com",
"ns2.example.com"
]
}
};
}
[TestMethod]
public async Task ShouldReturnZoneDetails()
{
// Arrange
var client = GetClient();
// Act
var response = await client.ZoneDetails(ZoneId);
// Assert
Assert.IsNotNull(response);
Assert.IsTrue(response.Success);
Assert.AreEqual(_response.Result, response.Result);
Assert.AreEqual(1, _callbacks.Count);
var callback = _callbacks.First();
Assert.AreEqual($"/zones/{ZoneId}", callback.RequestPath);
Assert.IsNull(callback.QueryFilter);
_clientMock.Verify(m => m.GetAsync<Zone>($"/zones/{ZoneId}", null, It.IsAny<CancellationToken>()), Times.Once);
_clientMock.VerifyNoOtherCalls();
}
private ICloudflareClient GetClient()
{
_clientMock = new Mock<ICloudflareClient>();
_clientMock
.Setup(m => m.GetAsync<Zone>(It.IsAny<string>(), It.IsAny<IQueryParameterFilter>(), It.IsAny<CancellationToken>()))
.Callback<string, IQueryParameterFilter, CancellationToken>((requestPath, queryFilter, _) => _callbacks.Add((requestPath, queryFilter)))
.ReturnsAsync(() => _response);
return _clientMock.Object;
}
}
}