Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added DebuggerDisplay to make debugging easier #16

Merged
merged 6 commits into from
Aug 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/CloudFlare.NET/CloudFlareAuth.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

/// <summary>
/// Represents the authorization parameters for accessing the CloudFlare API.
/// </summary>
/// <seealso href="https://api.cloudflare.com/#requests"/>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class CloudFlareAuth
{
/// <summary>
Expand All @@ -33,5 +35,7 @@ public CloudFlareAuth(string email, string key)
/// Gets the API key generated on the "My Account" page.
/// </summary>
public string Key { get; }

private string DebuggerDisplay => $"{GetType().Name}: {Email}";
}
}
14 changes: 14 additions & 0 deletions src/CloudFlare.NET/CloudFlareClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
Expand All @@ -10,6 +11,7 @@
using System.Threading.Tasks;

/// <inheritdoc/>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class CloudFlareClient : ICloudFlareClient
{
private static readonly Lazy<HttpClient> LazyClient = new Lazy<HttpClient>(
Expand Down Expand Up @@ -51,6 +53,18 @@ public CloudFlareClient(HttpClient client, CloudFlareAuth auth = null)
_auth = auth;
}

/// <summary>
/// Gets the <see cref="CloudFlareAuth"/> for this client.
/// </summary>
public CloudFlareAuth Auth => _auth;

/// <summary>
/// Gets the underlying HttpClient used to make requests.
/// </summary>
public HttpClient Client => _client;

private string DebuggerDisplay => $"{GetType().Name}: {_auth?.Email ?? string.Empty}";

/// <summary>
/// Creates the default <see cref="HttpClient"/>
/// </summary>
Expand Down
4 changes: 4 additions & 0 deletions src/CloudFlare.NET/CloudFlareError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Newtonsoft.Json;

/// <summary>
/// Represents an error that can occur as a result of a CloudFlare API request.
/// </summary>
/// <seealso href="https://api.cloudflare.com/#responses"/>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class CloudFlareError : IEquatable<CloudFlareError>
{
/// <summary>
Expand All @@ -32,6 +34,8 @@ public CloudFlareError(int code, string message = null)
[JsonProperty("message")]
public string Message { get; }

private string DebuggerDisplay => $"{GetType().Name}: {Code} '{Message}'";

/// <summary>
/// The implicit operator to return the <see cref="Code"/> of a <see cref="CloudFlareError"/>.
/// </summary>
Expand Down
4 changes: 4 additions & 0 deletions src/CloudFlare.NET/CloudFlareResponseBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Newtonsoft.Json;

/// <summary>
/// Represent the base response from CloudFlare indicating success or failure.
/// </summary>
/// <seealso href="https://api.cloudflare.com/#responses"/>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class CloudFlareResponseBase
{
private static readonly IReadOnlyList<CloudFlareError> EmptyErrors =
Expand Down Expand Up @@ -57,5 +59,7 @@ public CloudFlareResponseBase(
/// </summary>
[JsonProperty("result_info")]
public CloudFlareResultInfo ResultInfo { get; }

private string DebuggerDisplay => $"{GetType().Name}: Success={Success}";
}
}
5 changes: 4 additions & 1 deletion src/CloudFlare.NET/DnsRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;

/// <summary>
/// Represents a DNS record for a <see cref="Zone"/>.
/// </summary>
/// <seealso href="https://api.cloudflare.com/#dns-records-for-a-zone-properties"/>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class DnsRecord : IIdentifier, IModified
{
/// <summary>
Expand Down Expand Up @@ -143,5 +144,7 @@ public DnsRecord(
/// </summary>
[JsonProperty("priority")]
public int Priority { get; }

private string DebuggerDisplay => $"{GetType().Name}: {Type} {Name} => {Content}";
}
}
5 changes: 4 additions & 1 deletion src/CloudFlare.NET/Zone.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using CloudFlare.NET.Serialization;
using Newtonsoft.Json;

/// <summary>
/// A Zone is a domain name along with its subdomains and other identities.
/// </summary>
/// <seealso href="https://api.cloudflare.com/#zone-properties"/>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class Zone : IIdentifier, IModified
{
private static readonly IReadOnlyList<string> EmptyStrings = Enumerable.Empty<string>().ToArray();
Expand Down Expand Up @@ -103,5 +104,7 @@ public Zone(
/// </summary>
[JsonProperty("status")]
public ZoneStatusType Status { get; }

private string DebuggerDisplay => $"{GetType().Name}: {Name}";
}
}
1 change: 1 addition & 0 deletions src/Tests/CloudFlare.NET.Tests/CloudFlare.NET.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
<Compile Include="CloudFlareClientSpec.cs" />
<Compile Include="CloudFlareCustomization.cs" />
<Compile Include="CloudFlareErrorSpec.cs" />
<Compile Include="DebuggerDisplaySpec.cs" />
<Compile Include="DnsRecordClientExtensionsSpec.cs" />
<Compile Include="DnsRecordClientSpec.cs" />
<Compile Include="EqualsBehaviors.cs" />
Expand Down
18 changes: 18 additions & 0 deletions src/Tests/CloudFlare.NET.Tests/CloudFlareClientSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Net.Http;
using Machine.Specifications;
using Ploeh.AutoFixture;
using Ploeh.AutoFixture.Kernel;

[Subject(typeof(CloudFlareClient))]
public class When_creating_the_message_handler_pipeline_using_only_delegates : FixtureContext
Expand Down Expand Up @@ -99,4 +100,21 @@ public class When_creating_a_pipeline_with_a_HttpClientHandler_at_the_front : Fi

It should_throw_an_ArgumentException = () => _exception.ShouldBeOfExactType<ArgumentException>();
}

[Subject(typeof (CloudFlareClient))]
public class When_initialising_with_a_custom_HttpClient : FixtureContext
{
static HttpClient _httpClient;
static CloudFlareClient _sut;

Establish context = () =>
{
_httpClient = _fixture.Freeze<HttpClient>();
_fixture.Customize(new ConstructorCustomization(typeof(CloudFlareClient), new GreedyConstructorQuery()));
};

Because of = () => _sut = _fixture.Create<CloudFlareClient>();

It should_use_the_HttpClient = () => _sut.Client.ShouldBeTheSameAs(_httpClient);
}
}
180 changes: 180 additions & 0 deletions src/Tests/CloudFlare.NET.Tests/DebuggerDisplaySpec.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
namespace CloudFlare.NET.DebuggerDisplaySpec
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Machine.Specifications;
using Ploeh.AutoFixture;

public abstract class DebuggerDisplayContext<T> : FixtureContext
where T : class
{
protected static T _sut;
protected static DebuggerDisplayAttribute _debuggerDisplay;
protected static PropertyInfo _debuggerDisplayPropertyInfo;
protected static MethodInfo _debuggerDisplayGetMethod;
protected static object _debuggerDisplayValue;

/// <summary>
/// Returns the <see cref="DebuggerDisplayAttribute"/> data of the <see cref="_sut"/>
/// </summary>
/// <returns>The <see cref="DebuggerDisplayAttribute"/> data of the <see cref="_sut"/>.</returns>
protected static string GetDebuggerDisplay()
{
Type type = _sut.GetType();

_debuggerDisplay = type.GetCustomAttribute<DebuggerDisplayAttribute>(inherit: false);

_debuggerDisplayPropertyInfo =
type.GetProperty("DebuggerDisplay", BindingFlags.NonPublic | BindingFlags.Instance);

_debuggerDisplayGetMethod = _debuggerDisplayPropertyInfo.GetGetMethod(true);

_debuggerDisplayValue = _debuggerDisplayGetMethod.Invoke(_sut, new object[] {});

return _debuggerDisplayValue.ToString();
}
}

[Behaviors]
public class DebuggerDisplayBehavior
{
protected static object _sut;
protected static DebuggerDisplayAttribute _debuggerDisplay;
protected static PropertyInfo _debuggerDisplayPropertyInfo;
protected static MethodInfo _debuggerDisplayGetMethod;
protected static object _debuggerDisplayValue;

It should_have_the_debugger_display_attribute = () => _debuggerDisplay.ShouldNotBeNull();

It should_specify_the_debugger_display_property =
() => _debuggerDisplay.Value.ShouldEqual("{DebuggerDisplay,nq}");

It should_have_the_debugger_display_private_property = () => _debuggerDisplayPropertyInfo.ShouldNotBeNull();

It should_have_a_getter_on_the_debugger_display_property = () => _debuggerDisplayGetMethod.ShouldNotBeNull();

It should_provide_a_string_display_property = () => _debuggerDisplayValue.ShouldBeOfExactType<string>();

It should_include_the_type_in_the_debugger_display =
() => _debuggerDisplayValue.ToString().ShouldStartWith($"{_sut.GetType().Name}:");
}

namespace CloudFlareAuthSpec
{
[Subject(typeof(CloudFlareAuth))]
public class When_running_in_the_debugger : DebuggerDisplayContext<CloudFlareAuth>
{
static string _debuggerDisplayText;

Establish contect = () => _sut = _fixture.Create<CloudFlareAuth>();

Because of = () => _debuggerDisplayText = GetDebuggerDisplay();

Behaves_like<DebuggerDisplayBehavior> debugger_display_behaviour;

It should_include_the_email_in_the_debugger_display = () => _debuggerDisplayText.ShouldContain(_sut.Email);
}
}

namespace CloudFlareClientSpec
{
[Subject(typeof(CloudFlareClient))]
public class When_running_in_the_debugger : DebuggerDisplayContext<CloudFlareClient>
{
static string _debuggerDisplayText;

Establish contect = () => _sut = _fixture.Create<CloudFlareClient>();

Because of = () => _debuggerDisplayText = GetDebuggerDisplay();

Behaves_like<DebuggerDisplayBehavior> debugger_display_behaviour;

It should_include_the_authentication_email_in_the_debugger_display =
() => _debuggerDisplayText.ShouldContain(_sut.Auth.Email);
}
}

namespace CloudFlareErrorSpec
{
[Subject(typeof(CloudFlareError))]
public class When_running_in_the_debugger : DebuggerDisplayContext<CloudFlareError>
{
static string _debuggerDisplayText;

Establish contect = () => _sut = _fixture.Create<CloudFlareError>();

Because of = () => _debuggerDisplayText = GetDebuggerDisplay();

Behaves_like<DebuggerDisplayBehavior> debugger_display_behaviour;

It should_include_the_code_in_the_debugger_display =
() => _debuggerDisplayText.ShouldContain(_sut.Code.ToString());

It should_include_the_message_in_the_debugger_display =
() => _debuggerDisplayText.ShouldContain(_sut.Message);
}
}

namespace CloudFlareResponseBaseSpec
{
[Subject(typeof(CloudFlareResponseBase))]
public class When_running_in_the_debugger : DebuggerDisplayContext<CloudFlareResponseBase>
{
static string _debuggerDisplayText;

Establish contect = () => _sut = _fixture.Create<CloudFlareResponseBase>();

Because of = () => _debuggerDisplayText = GetDebuggerDisplay();

Behaves_like<DebuggerDisplayBehavior> debugger_display_behaviour;

It should_include_the_success_status_in_the_debugger_display =
() => _debuggerDisplayText.ShouldContain($"Success={_sut.Success}");
}
}

namespace DnsRecordSpec
{
[Subject(typeof(DnsRecord))]
public class When_running_in_the_debugger : DebuggerDisplayContext<DnsRecord>
{
static string _debuggerDisplayText;

Establish contect = () => _sut = _fixture.Create<DnsRecord>();

Because of = () => _debuggerDisplayText = GetDebuggerDisplay();

Behaves_like<DebuggerDisplayBehavior> debugger_display_behaviour;

It should_include_the_type_in_the_debugger_display =
() => _debuggerDisplayText.ShouldContain($"{_sut.Type}");

It should_include_the_name_in_the_debugger_display =
() => _debuggerDisplayText.ShouldContain($"{_sut.Name}");

It should_include_the_content_in_the_debugger_display =
() => _debuggerDisplayText.ShouldContain($"{_sut.Content}");
}
}

namespace ZoneSpec
{
[Subject(typeof(Zone))]
public class When_running_in_the_debugger : DebuggerDisplayContext<Zone>
{
static string _debuggerDisplayText;

Establish contect = () => _sut = _fixture.Create<Zone>();

Because of = () => _debuggerDisplayText = GetDebuggerDisplay();

Behaves_like<DebuggerDisplayBehavior> debugger_display_behaviour;

It should_include_the_name_in_the_debugger_display =
() => _debuggerDisplayText.ShouldContain($"{_sut.Name}");
}
}
}