Skip to content

Commit

Permalink
Add Combination callbacks (#1334)
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonCropp authored Oct 30, 2024
1 parent c3f348b commit 2df474a
Show file tree
Hide file tree
Showing 17 changed files with 352 additions and 145 deletions.
16 changes: 8 additions & 8 deletions docs/combinations.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ Exception capture can be enable globally:
```cs
[ModuleInitializer]
public static void Initialize() =>
VerifyCombinationSettings.CaptureExceptions();
CombinationSettings.CaptureExceptions();
```
<sup><a href='/src/StaticSettingsTests/VerifyCombinationsTests.cs#L3-L9' title='Snippet source file'>snippet source</a> | <a href='#snippet-GlobalCaptureExceptions' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/StaticSettingsTests/CombinationsTests.cs#L3-L9' title='Snippet source file'>snippet source</a> | <a href='#snippet-GlobalCaptureExceptions' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

If exception capture has been enabled globally, it can be disable at the method test level using `captureExceptions: false`.
Expand All @@ -173,7 +173,7 @@ public Task BuildAddressExceptionsDisabledTest()
cities);
}
```
<sup><a href='/src/StaticSettingsTests/VerifyCombinationsTests.cs#L68-L84' title='Snippet source file'>snippet source</a> | <a href='#snippet-CombinationSample_CaptureExceptionsFalse' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/StaticSettingsTests/CombinationsTests.cs#L177-L193' title='Snippet source file'>snippet source</a> | <a href='#snippet-CombinationSample_CaptureExceptionsFalse' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down Expand Up @@ -335,7 +335,7 @@ class CustomCombinationConverter :
string.Join(", ", keys.Select(_ => _.Value));
}
```
<sup><a href='/src/StaticSettingsTests/VerifyCombinationsTests.cs#L114-L123' title='Snippet source file'>snippet source</a> | <a href='#snippet-CombinationSample_CustomSerializationConverter' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/StaticSettingsTests/CombinationsTests.cs#L223-L232' title='Snippet source file'>snippet source</a> | <a href='#snippet-CombinationSample_CustomSerializationConverter' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Full control of serialization can be achieved by inheriting from `WriteOnlyJsonConverter<CombinationResults>`.
Expand All @@ -354,14 +354,14 @@ static CustomCombinationConverter customConverter = new();
public static void Init() =>
VerifierSettings.AddExtraSettings(_ => _.Converters.Insert(0, customConverter));
```
<sup><a href='/src/StaticSettingsTests/VerifyCombinationsTests.cs#L86-L94' title='Snippet source file'>snippet source</a> | <a href='#snippet-CombinationSample_CustomSerializationModuleInitializer' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/StaticSettingsTests/CombinationsTests.cs#L195-L203' title='Snippet source file'>snippet source</a> | <a href='#snippet-CombinationSample_CustomSerializationModuleInitializer' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


#### Result

<!-- snippet: VerifyCombinationsTests.Combination_CustomSerialization.verified.txt -->
<a id='snippet-VerifyCombinationsTests.Combination_CustomSerialization.verified.txt'></a>
<!-- snippet: CombinationsTests.Combination_CustomSerialization.verified.txt -->
<a id='snippet-CombinationsTests.Combination_CustomSerialization.verified.txt'></a>
```txt
{
1, Smith St, Sydney: 1 Smith St, Sydney,
Expand All @@ -374,5 +374,5 @@ public static void Init() =>
10, Wallace St, Chicago: 10 Wallace St, Chicago
}
```
<sup><a href='/src/StaticSettingsTests/VerifyCombinationsTests.Combination_CustomSerialization.verified.txt#L1-L10' title='Snippet source file'>snippet source</a> | <a href='#snippet-VerifyCombinationsTests.Combination_CustomSerialization.verified.txt' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/StaticSettingsTests/CombinationsTests.Combination_CustomSerialization.verified.txt#L1-L10' title='Snippet source file'>snippet source</a> | <a href='#snippet-CombinationsTests.Combination_CustomSerialization.verified.txt' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
2 changes: 1 addition & 1 deletion docs/mdsource/combinations.source.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,4 @@ snippet: CombinationSample_CustomSerializationModuleInitializer

#### Result

snippet: VerifyCombinationsTests.Combination_CustomSerialization.verified.txt
snippet: CombinationsTests.Combination_CustomSerialization.verified.txt
5 changes: 4 additions & 1 deletion src/StaticSettingsTests/BaseTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

public abstract class BaseTest
{
protected BaseTest() =>
protected BaseTest()
{
VerifierSettings.Reset();
CombinationSettings.Reset();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
beforeKeys: [
10,
value2
],
afterKeys: [
10,
value2
],
afterResult: 10 value2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
1, value1: 1 value1,
1, value2: 1 value2,
10, value1: 10 value1,
10, value2: 10 value2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
beforeKeys: [
10,
value2
],
exceptionKeys: [
10,
value2
],
exceptionResult: {
$type: Exception,
Type: Exception,
Message: Message
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
1, value1: Exception: Message,
1, value2: Exception: Message,
10, value1: Exception: Message,
10, value2: Exception: Message
}
233 changes: 233 additions & 0 deletions src/StaticSettingsTests/CombinationsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
public class CombinationsTests
{
#region GlobalCaptureExceptions

[ModuleInitializer]
public static void Initialize() =>
CombinationSettings.CaptureExceptions();

#endregion

[Fact]
public Task Defaults()
{
string[] list = ["A", "b", "C"];
return Combination().Verify(
_ => _.ToLower(),
list);
}

[Fact]
public async Task CallbacksTest()
{
var beforeCalled = false;
IReadOnlyList<object?>? beforeKeys = null;
object? afterResult = null;
IReadOnlyList<object?>? afterKeys = null;
IReadOnlyList<object?>? exceptionKeys = null;
Exception? exceptionResult = null;
var afterCalled = false;
var exceptionCalled = false;
int[] params1 = [1, 10];
string[] params2 = ["value1", "value2"];
CombinationSettings.UseCallbacks(
keys =>
{
beforeKeys = keys;
beforeCalled = true;
return Task.CompletedTask;
},
(keys, result) =>
{
afterResult = result;
afterKeys = keys;
afterCalled = true;
return Task.CompletedTask;
},
(keys, exception) =>
{
exceptionResult = exception;
exceptionKeys = keys;
exceptionCalled = true;
return Task.CompletedTask;
});
await Combination()
.Verify(
(param1, param2) => $"{param1} {param2}",
params1,
params2);
Assert.True(beforeCalled);
Assert.True(afterCalled);
Assert.False(exceptionCalled);
await Verify(new
{
beforeKeys,
afterKeys,
afterResult,
exceptionKeys,
exceptionResult
})
.UseMethodName("CallbackResults");
}

[Fact]
public async Task ExceptionCallbacksTest()
{
var beforeCalled = false;
IReadOnlyList<object?>? beforeKeys = null;
object? afterResult = null;
IReadOnlyList<object?>? afterKeys = null;
IReadOnlyList<object?>? exceptionKeys = null;
Exception? exceptionResult = null;
var afterCalled = false;
var exceptionCalled = false;
int[] params1 = [1, 10];
string[] params2 = ["value1", "value2"];
CombinationSettings.UseCallbacks(
keys =>
{
beforeKeys = keys;
beforeCalled = true;
return Task.CompletedTask;
},
(keys, result) =>
{
afterResult = result;
afterKeys = keys;
afterCalled = true;
return Task.CompletedTask;
},
(keys, exception) =>
{
exceptionResult = exception;
exceptionKeys = keys;
exceptionCalled = true;
return Task.CompletedTask;
});

static string Method(int i, string s) =>
throw new("Message");

await Combination()
.Verify(
Method,
params1,
params2);
Assert.True(beforeCalled);
Assert.False(afterCalled);
Assert.True(exceptionCalled);
await Verify(new
{
beforeKeys,
afterKeys,
afterResult,
exceptionKeys,
exceptionResult
})
.UseMethodName("ExceptionCallbackResults")
.IgnoreStackTrace();
}

[Fact]
public Task WithCaptureExceptions()
{
string[] a = ["A", "b", "C"];
return Combination(captureExceptions: true)
.Verify(
a =>
{
if (a == "b")
{
throw new ArgumentException("B is not allowed");
}
return a.ToLower();
},
a);
}

[Fact]
public Task WithNoCaptureExceptions()
{
string[] a = ["A", "b", "C"];
return Assert.ThrowsAsync<ArgumentException>(
() => Combination(captureExceptions: false)
.Verify(
a =>
{
if (a == "b")
{
throw new ArgumentException("B is not allowed");
}
return a.ToLower();
},
a));
}

static string BuildAddress(int streetNumber, string street, string city)
{
ArgumentException.ThrowIfNullOrWhiteSpace(street);
ArgumentException.ThrowIfNullOrWhiteSpace(city);
ArgumentOutOfRangeException.ThrowIfLessThan(streetNumber, 1);

return $"{streetNumber} {street}, {city}";
}

#region CombinationSample_CaptureExceptionsFalse

[Fact]
public Task BuildAddressExceptionsDisabledTest()
{
int[] streetNumbers = [1, 10];
string[] streets = ["Smith St", "Wallace St"];
string[] cities = ["Sydney", "Chicago"];
return Combination(captureExceptions: false)
.Verify(
BuildAddress,
streetNumbers,
streets,
cities);
}

#endregion

#region CombinationSample_CustomSerializationModuleInitializer

static CustomCombinationConverter customConverter = new();

[ModuleInitializer]
public static void Init() =>
VerifierSettings.AddExtraSettings(_ => _.Converters.Insert(0, customConverter));

#endregion

#region CombinationSample_CustomSerialization

[Fact]
public Task Combination_CustomSerialization()
{
int[] streetNumbers = [1, 10];
string[] streets = ["Smith St", "Wallace St"];
string[] cities = ["Sydney", "Chicago"];
return Combination()
.Verify(
BuildAddress,
streetNumbers,
streets,
cities);
}

#endregion

#region CombinationSample_CustomSerializationConverter

class CustomCombinationConverter :
CombinationResultsConverter
{
protected override string BuildPropertyName(IReadOnlyList<CombinationKey> keys) =>
string.Join(", ", keys.Select(_ => _.Value));
}

#endregion
}
Loading

0 comments on commit 2df474a

Please sign in to comment.