Skip to content

Commit

Permalink
Allow properties to be included even when they are the default value (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
JustASquid committed Mar 7, 2024
1 parent 021e5e6 commit 09c6466
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 23 deletions.
66 changes: 51 additions & 15 deletions docs/serializer-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ public Task ScopedSerializerFluent()
.AddExtraSettings(_ => _.TypeNameHandling = TypeNameHandling.All);
}
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3695-L3722' title='Snippet source file'>snippet source</a> | <a href='#snippet-scopedserializer' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3698-L3725' title='Snippet source file'>snippet source</a> | <a href='#snippet-scopedserializer' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Result:
Expand Down Expand Up @@ -799,7 +799,7 @@ public Task WithObsoleteProp()
return Verify(target);
}
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3660-L3681' title='Snippet source file'>snippet source</a> | <a href='#snippet-withobsoleteprop' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3663-L3684' title='Snippet source file'>snippet source</a> | <a href='#snippet-withobsoleteprop' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Result:
Expand Down Expand Up @@ -847,7 +847,7 @@ public Task WithObsoletePropIncludedFluent()
.IncludeObsoletes();
}
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3631-L3658' title='Snippet source file'>snippet source</a> | <a href='#snippet-withobsoletepropincluded' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3634-L3661' title='Snippet source file'>snippet source</a> | <a href='#snippet-withobsoletepropincluded' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Or globally:
Expand All @@ -857,7 +857,7 @@ Or globally:
```cs
VerifierSettings.IncludeObsoletes();
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3624-L3628' title='Snippet source file'>snippet source</a> | <a href='#snippet-withobsoletepropincludedglobally' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3627-L3631' title='Snippet source file'>snippet source</a> | <a href='#snippet-withobsoletepropincludedglobally' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Result:
Expand Down Expand Up @@ -918,7 +918,7 @@ public Task IgnoreMemberByExpressionFluent()
_ => _.PropertyThatThrows);
}
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3142-L3181' title='Snippet source file'>snippet source</a> | <a href='#snippet-ignorememberbyexpression' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3145-L3184' title='Snippet source file'>snippet source</a> | <a href='#snippet-ignorememberbyexpression' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Or globally
Expand All @@ -933,7 +933,7 @@ VerifierSettings.IgnoreMembers<IgnoreExplicitTarget>(
_ => _.GetOnlyProperty,
_ => _.PropertyThatThrows);
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3119-L3128' title='Snippet source file'>snippet source</a> | <a href='#snippet-ignorememberbyexpressionglobal' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3122-L3131' title='Snippet source file'>snippet source</a> | <a href='#snippet-ignorememberbyexpressionglobal' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Result:
Expand Down Expand Up @@ -993,7 +993,7 @@ public Task ScrubMemberByExpressionFluent()
_ => _.PropertyThatThrows);
}
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3183-L3222' title='Snippet source file'>snippet source</a> | <a href='#snippet-scrubmemberbyexpression' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3186-L3225' title='Snippet source file'>snippet source</a> | <a href='#snippet-scrubmemberbyexpression' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Or globally
Expand All @@ -1008,7 +1008,7 @@ VerifierSettings.ScrubMembers<IgnoreExplicitTarget>(
_ => _.GetOnlyProperty,
_ => _.PropertyThatThrows);
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3130-L3139' title='Snippet source file'>snippet source</a> | <a href='#snippet-scrubmemberbyexpressionglobal' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3133-L3142' title='Snippet source file'>snippet source</a> | <a href='#snippet-scrubmemberbyexpressionglobal' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Result:
Expand Down Expand Up @@ -1087,7 +1087,7 @@ public Task IgnoreMemberByNameFluent()
.IgnoreMember<IgnoreExplicitTarget>(_ => _.PropertyThatThrows);
}
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3296-L3349' title='Snippet source file'>snippet source</a> | <a href='#snippet-ignorememberbyname' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3299-L3352' title='Snippet source file'>snippet source</a> | <a href='#snippet-ignorememberbyname' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Or globally:
Expand All @@ -1107,7 +1107,7 @@ VerifierSettings.IgnoreMember<IgnoreExplicitTarget>("Field");
// For a specific type with expression
VerifierSettings.IgnoreMember<IgnoreExplicitTarget>(_ => _.PropertyThatThrows);
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3263-L3277' title='Snippet source file'>snippet source</a> | <a href='#snippet-ignorememberbynameglobal' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3266-L3280' title='Snippet source file'>snippet source</a> | <a href='#snippet-ignorememberbynameglobal' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Result:
Expand Down Expand Up @@ -1182,7 +1182,7 @@ public Task ScrubMemberByNameFluent()
.ScrubMember<IgnoreExplicitTarget>(_ => _.PropertyThatThrows);
}
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3351-L3404' title='Snippet source file'>snippet source</a> | <a href='#snippet-scrubmemberbyname' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3354-L3407' title='Snippet source file'>snippet source</a> | <a href='#snippet-scrubmemberbyname' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Or globally:
Expand All @@ -1202,7 +1202,7 @@ VerifierSettings.ScrubMember<IgnoreExplicitTarget>("Field");
// For a specific type with expression
VerifierSettings.ScrubMember<IgnoreExplicitTarget>(_ => _.PropertyThatThrows);
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3279-L3293' title='Snippet source file'>snippet source</a> | <a href='#snippet-scrubmemberbynameglobal' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3282-L3296' title='Snippet source file'>snippet source</a> | <a href='#snippet-scrubmemberbynameglobal' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Result:
Expand Down Expand Up @@ -1253,7 +1253,7 @@ public Task CustomExceptionPropFluent()
.IgnoreMembersThatThrow<CustomException>();
}
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3512-L3531' title='Snippet source file'>snippet source</a> | <a href='#snippet-ignoremembersthatthrow' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3515-L3534' title='Snippet source file'>snippet source</a> | <a href='#snippet-ignoremembersthatthrow' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Or globally:
Expand All @@ -1263,7 +1263,7 @@ Or globally:
```cs
VerifierSettings.IgnoreMembersThatThrow<CustomException>();
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3505-L3509' title='Snippet source file'>snippet source</a> | <a href='#snippet-ignoremembersthatthrowglobal' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3508-L3512' title='Snippet source file'>snippet source</a> | <a href='#snippet-ignoremembersthatthrowglobal' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Result:
Expand Down Expand Up @@ -1323,6 +1323,42 @@ Result:
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.ExceptionMessageProp.verified.txt#L1-L1' title='Snippet source file'>snippet source</a> | <a href='#snippet-SerializationTests.ExceptionMessageProp.verified.txt' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## Always Include Members

Sometimes it's convenient for certain members/types to always be included in the Verify output, even when they are equal to their default value.
The biggest example is numeric types e.g. `int` or `double` - output could be more consistent if values might fluctuate between zero and non-zero.

<!-- snippet: AlwaysIncludeType -->
<a id='snippet-alwaysincludetype'></a>
```cs
[Fact]
public Task AlwaysIncludeType()
{
var target = new
{
A = 0.0,
B = 1e-26
};

return Verify(target)
.AlwaysIncludeMembersWithType<double>();
}
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L2976-L2987' title='Snippet source file'>snippet source</a> | <a href='#snippet-alwaysincludetype' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Result:

<!-- snippet: SerializationTests.AlwaysIncludeType.verified.txt -->
<a id='snippet-SerializationTests.AlwaysIncludeType.verified.txt'></a>
```txt
{
A: 0.0,
B: 1E-26
}
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.AlwaysIncludeType.verified.txt#L1-L4' title='Snippet source file'>snippet source</a> | <a href='#snippet-SerializationTests.AlwaysIncludeType.verified.txt' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## TreatAsString

Expand Down Expand Up @@ -1468,7 +1504,7 @@ public Task MemberConverterByExpression()
return Verify(input);
}
```
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3224-L3252' title='Snippet source file'>snippet source</a> | <a href='#snippet-memberconverter' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/Serialization/SerializationTests.cs#L3227-L3255' title='Snippet source file'>snippet source</a> | <a href='#snippet-memberconverter' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"A": 0.0,
"B": 1E-26
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
A: 0.0,
B: 1E-26
}
13 changes: 13 additions & 0 deletions src/Verify.Tests/Serialization/SerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2985,6 +2985,19 @@ class IgnoreMembersNullableNestedTarget
public ToIgnoreStruct? ToIgnoreStruct { get; set; }
}

[Fact]
public Task AlwaysIncludeType()
{
var target = new
{
A = 0.0,
B = 1e-26
};

return Verify(target)
.AlwaysIncludeMembersWithType<double>();
}

[Fact]
public Task Type() =>
Verify(GetType());
Expand Down
19 changes: 12 additions & 7 deletions src/Verify/Serialization/CustomContractResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,19 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ

if (settings.TryGetScrubOrIgnore(member, out var scrubOrIgnore))
{
if (scrubOrIgnore == ScrubOrIgnore.Ignore)
switch (scrubOrIgnore)
{
property.Ignored = true;
}
else
{
property.PropertyType = typeof(string);
property.ValueProvider = new ScrubbedProvider();
case ScrubOrIgnore.AlwaysInclude:
property.Ignored = false;
property.DefaultValueHandling = DefaultValueHandling.Include;
break;
case ScrubOrIgnore.Ignore:
property.Ignored = true;
break;
case ScrubOrIgnore.Scrub:
property.PropertyType = typeof(string);
property.ValueProvider = new ScrubbedProvider();
break;
}

return property;
Expand Down
3 changes: 2 additions & 1 deletion src/Verify/Serialization/ScrubOrIgnore.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
enum ScrubOrIgnore
{
Scrub,
Ignore
Ignore,
AlwaysInclude
}
7 changes: 7 additions & 0 deletions src/Verify/Serialization/SerializationSettings_IgnoreType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ public void IgnoreMembersWithType<T>()
public void IgnoreMembersWithType(Type type) =>
Add(type, ScrubOrIgnore.Ignore);

public void AlwaysIncludeMembersWithType<T>()
where T : notnull =>
AlwaysIncludeMembersWithType(typeof(T));

public void AlwaysIncludeMembersWithType(Type type) =>
Add(type, ScrubOrIgnore.AlwaysInclude);

void Add(Type type, ScrubOrIgnore scrubOrIgnore)
{
ignoredTypes[type] = scrubOrIgnore;
Expand Down
13 changes: 13 additions & 0 deletions src/Verify/Serialization/VerifierSettings_SerializationMaps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,13 @@ public static void ScrubMembersWithType<T>()
serialization.ScrubMembersWithType<T>();
}

public static void AlwaysIncludeMembersWithType<T>()
where T : notnull
{
InnerVerifier.ThrowIfVerifyHasBeenRun();
serialization.AlwaysIncludeMembersWithType<T>();
}

public static void IgnoreMembersWithType(Type type)
{
InnerVerifier.ThrowIfVerifyHasBeenRun();
Expand All @@ -236,6 +243,12 @@ public static void ScrubMembersWithType(Type type)
serialization.ScrubMembersWithType(type);
}

public static void AlwaysIncludeMembersWithType(Type type)
{
InnerVerifier.ThrowIfVerifyHasBeenRun();
serialization.AlwaysIncludeMembersWithType(type);
}

public static void IgnoreMembersThatThrow<T>()
where T : Exception
{
Expand Down
13 changes: 13 additions & 0 deletions src/Verify/Serialization/VerifySettings_SerializationMaps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,13 @@ public void ScrubMembersWithType<T>()
serialization.ScrubMembersWithType<T>();
}

public void AlwaysIncludeMembersWithType<T>()
where T : notnull
{
CloneSettings();
serialization.AlwaysIncludeMembersWithType<T>();
}

public void IgnoreMembersWithType(Type type)
{
CloneSettings();
Expand All @@ -206,6 +213,12 @@ public void ScrubMembersWithType(Type type)
serialization.ScrubMembersWithType(type);
}

public void AlwaysIncludeMembersWithType(Type type)
{
CloneSettings();
serialization.AlwaysIncludeMembersWithType(type);
}

public void IgnoreMembersThatThrow<T>()
where T : Exception
{
Expand Down
15 changes: 15 additions & 0 deletions src/Verify/SettingsTask_SerializationMaps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,14 @@ public SettingsTask ScrubMembersWithType<T>()
return this;
}

[Pure]
public SettingsTask AlwaysIncludeMembersWithType<T>()
where T : notnull
{
CurrentSettings.AlwaysIncludeMembersWithType<T>();
return this;
}

[Pure]
public SettingsTask IgnoreMembersWithType(Type type)
{
Expand All @@ -231,6 +239,13 @@ public SettingsTask ScrubMembersWithType(Type type)
return this;
}

[Pure]
public SettingsTask AlwaysIncludeMembersWithType(Type type)
{
CurrentSettings.AlwaysIncludeMembersWithType(type);
return this;
}

[Pure]
public SettingsTask IgnoreMembersThatThrow<T>()
where T : Exception
Expand Down

0 comments on commit 09c6466

Please sign in to comment.