diff --git a/docs/diff-tool.md b/docs/diff-tool.md
index 7c0997878b..80374fc44f 100644
--- a/docs/diff-tool.md
+++ b/docs/diff-tool.md
@@ -57,7 +57,7 @@ This value can be changed:
```cs
DiffRunner.MaxInstancesToLaunch(10);
```
-snippet source | anchor
+snippet source | anchor
@@ -381,7 +381,7 @@ This behavior is currently supported on Windows. On Linux and OSX, diff tool ins
var settings = new VerifySettings();
settings.DisableDiff();
```
-snippet source | anchor
+snippet source | anchor
diff --git a/docs/named-tuples.md b/docs/named-tuples.md
index 1a7d790191..4621fd04bc 100644
--- a/docs/named-tuples.md
+++ b/docs/named-tuples.md
@@ -21,7 +21,7 @@ static (bool Member1, string Member2, string Member3) MethodWithNamedTuple()
return (true, "A", "B");
}
```
-snippet source | anchor
+snippet source | anchor
Can be verified:
@@ -31,7 +31,7 @@ Can be verified:
```cs
await Verify(() => MethodWithNamedTuple());
```
-snippet source | anchor
+snippet source | anchor
Resulting in:
diff --git a/docs/serializer-settings.md b/docs/serializer-settings.md
index d76bc92c61..00040840b4 100644
--- a/docs/serializer-settings.md
+++ b/docs/serializer-settings.md
@@ -97,7 +97,7 @@ var target = new GuidTarget
await Verify(target);
```
-snippet source | anchor
+snippet source | anchor
Results in the following:
@@ -147,7 +147,7 @@ var target = new DateTimeTarget
await Verify(target);
```
-snippet source | anchor
+snippet source | anchor
Results in the following:
@@ -241,7 +241,7 @@ settings.AddExtraSettings(_ =>
_.TypeNameHandling = TypeNameHandling.All;
});
```
-snippet source | anchor
+snippet source | anchor
@@ -262,7 +262,7 @@ settings.ModifySerialization(
settings.AddExtraSettings(
_ => { _.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat; });
```
-snippet source | anchor
+snippet source | anchor
Result:
@@ -303,7 +303,7 @@ var target = new IgnoreTypeTarget
};
await Verify(target, settings);
```
-snippet source | anchor
+snippet source | anchor
Result:
@@ -345,7 +345,7 @@ var target = new IgnoreInstanceTarget
};
await Verify(target, settings);
```
-snippet source | anchor
+snippet source | anchor
Result:
@@ -387,7 +387,7 @@ public Task WithObsoleteProp()
return Verify(target);
}
```
-snippet source | anchor
+snippet source | anchor
Result:
@@ -423,7 +423,7 @@ public Task WithObsoletePropIncluded()
return Verify(target, settings);
}
```
-snippet source | anchor
+snippet source | anchor
Result:
@@ -465,7 +465,7 @@ var target = new IgnoreExplicitTarget
};
await Verify(target, settings);
```
-snippet source | anchor
+snippet source | anchor
Result:
@@ -508,7 +508,7 @@ var target = new IgnoreExplicitTarget
};
await Verify(target, settings);
```
-snippet source | anchor
+snippet source | anchor
Result:
@@ -543,7 +543,7 @@ settings.ModifySerialization(_ => _.IgnoreMembersThatThrow());
var target = new WithCustomException();
await Verify(target, settings);
```
-snippet source | anchor
+snippet source | anchor
Result:
@@ -568,7 +568,7 @@ settings.ModifySerialization(
var target = new WithExceptionIgnoreMessage();
await Verify(target, settings);
```
-snippet source | anchor
+snippet source | anchor
Result:
@@ -591,7 +591,7 @@ By default newlines in json are escaped with `\r\n`:
```cs
return Verify(new {Property ="a\r\nb"});
```
-snippet source | anchor
+snippet source | anchor
@@ -613,7 +613,7 @@ var settings = new VerifySettings();
settings.DisableNewLineEscaping();
await Verify(new {Property = "a\r\nb"}, settings);
```
-snippet source | anchor
+snippet source | anchor
diff --git a/readme.md b/readme.md
index e577a7221a..3a6db73f73 100644
--- a/readme.md
+++ b/readme.md
@@ -31,6 +31,7 @@ Support is available via a [Tidelift Subscription](https://tidelift.com/subscrip
* [Subsequent Verification](#subsequent-verification)
* [Disable Clipboard](#disable-clipboard)
* [AutoVerify](#autoverify)
+ * [OnHandlers](#onhandlers)
* [Received and Verified](#received-and-verified)
* [Not valid json](#not-valid-json)
* [Extensions](#extensions)
@@ -451,7 +452,7 @@ The clipboard behavior can be disable using the following:
var settings = new VerifySettings();
settings.DisableClipboard();
```
-snippet source | anchor
+snippet source | anchor
@@ -469,12 +470,44 @@ This can be done using `AutoVerify()`:
var settings = new VerifySettings();
settings.AutoVerify();
```
-snippet source | anchor
+snippet source | anchor
Note that auto accepted changes in `.verified.` files remain visible in source control tooling.
+### OnHandlers
+
+`OnFirstVerify` is called when there is no verified file.
+
+`OnVerifyMismatch` is called when a received file does not match the existing verified file.
+
+
+
+```cs
+public async Task OnHandlersSample()
+{
+ var settings = new VerifySettings();
+ settings.OnFirstVerify(
+ receivedFile =>
+ {
+ Debug.WriteLine(receivedFile);
+ return Task.CompletedTask;
+ });
+ settings.OnVerifyMismatch(
+ (receivedFile, verifiedFile) =>
+ {
+ Debug.WriteLine(receivedFile);
+ Debug.WriteLine(verifiedFile);
+ return Task.CompletedTask;
+ });
+ await Verify("value", settings);
+}
+```
+snippet source | anchor
+
+
+
## Received and Verified
* **All `*.verified.*` files should be committed to source control.**
diff --git a/readme.source.md b/readme.source.md
index 6864cb738a..08e035dee9 100644
--- a/readme.source.md
+++ b/readme.source.md
@@ -193,6 +193,15 @@ snippet: AutoVerify
Note that auto accepted changes in `.verified.` files remain visible in source control tooling.
+### OnHandlers
+
+`OnFirstVerify` is called when there is no verified file.
+
+`OnVerifyMismatch` is called when a received file does not match the existing verified file.
+
+snippet: OnHandlers
+
+
## Received and Verified
* **All `*.verified.*` files should be committed to source control.**
diff --git a/src/Verify.Tests/Snippets/Snippets.cs b/src/Verify.Tests/Snippets/Snippets.cs
index c0452669b9..23736132fe 100644
--- a/src/Verify.Tests/Snippets/Snippets.cs
+++ b/src/Verify.Tests/Snippets/Snippets.cs
@@ -1,9 +1,36 @@
using System;
+using System.Diagnostics;
+using System.Threading.Tasks;
using Newtonsoft.Json;
using Verify;
+using VerifyXunit;
+using Xunit;
+using Xunit.Abstractions;
-public class Snippets
+public class Snippets:
+ VerifyBase
{
+ #region OnHandlers
+ public async Task OnHandlersSample()
+ {
+ var settings = new VerifySettings();
+ settings.OnFirstVerify(
+ receivedFile =>
+ {
+ Debug.WriteLine(receivedFile);
+ return Task.CompletedTask;
+ });
+ settings.OnVerifyMismatch(
+ (receivedFile, verifiedFile) =>
+ {
+ Debug.WriteLine(receivedFile);
+ Debug.WriteLine(verifiedFile);
+ return Task.CompletedTask;
+ });
+ await Verify("value", settings);
+ }
+ #endregion
+
void DisableClipboard()
{
#region DisableClipboard
@@ -66,4 +93,9 @@ public void ScopedSerializer()
#endregion
}
+
+ public Snippets(ITestOutputHelper output) :
+ base(output)
+ {
+ }
}
\ No newline at end of file
diff --git a/src/Verify.Tests/Tests.OnVerifyMismatch.verified.txt b/src/Verify.Tests/Tests.OnVerifyMismatch.verified.txt
new file mode 100644
index 0000000000..786cc90368
--- /dev/null
+++ b/src/Verify.Tests/Tests.OnVerifyMismatch.verified.txt
@@ -0,0 +1 @@
+othervalue
\ No newline at end of file
diff --git a/src/Verify.Tests/Tests.cs b/src/Verify.Tests/Tests.cs
index 8cd8c1cf93..2f9bc18329 100644
--- a/src/Verify.Tests/Tests.cs
+++ b/src/Verify.Tests/Tests.cs
@@ -8,6 +8,7 @@
using VerifyXunit;
using Xunit;
using Xunit.Abstractions;
+using Xunit.Sdk;
// Non-nullable field is uninitialized.
#pragma warning disable CS8618
@@ -27,6 +28,62 @@ public Task ScrubCurrentDirectory()
return Verify(Environment.CurrentDirectory.TrimEnd('/', '\\'));
}
+ [Fact]
+ public async Task OnVerifyMismatch()
+ {
+ var settings = new VerifySettings();
+ settings.DisableDiff();
+ settings.DisableClipboard();
+ var onFirstVerifyCalled = false;
+ var onVerifyMismatchCalled = false;
+ settings.OnFirstVerify(
+ receivedFile =>
+ {
+ onFirstVerifyCalled = true;
+ return Task.CompletedTask;
+ });
+ settings.OnVerifyMismatch(
+ (receivedFile, verifiedFile) =>
+ {
+ Assert.NotEmpty(receivedFile);
+ Assert.NotNull(receivedFile);
+ Assert.NotEmpty(verifiedFile);
+ Assert.NotNull(verifiedFile);
+ onVerifyMismatchCalled = true;
+ return Task.CompletedTask;
+ });
+ await Assert.ThrowsAsync(() => Verify("value", settings));
+ Assert.False(onFirstVerifyCalled);
+ Assert.True(onVerifyMismatchCalled);
+ }
+
+ [Fact]
+ public async Task OnFirstVerify()
+ {
+ var settings = new VerifySettings();
+ settings.DisableDiff();
+ settings.DisableClipboard();
+ var onFirstVerifyCalled = false;
+ var onVerifyMismatchCalled = false;
+ settings.OnFirstVerify(
+ receivedFile =>
+ {
+ Assert.NotEmpty(receivedFile);
+ Assert.NotNull(receivedFile);
+ onFirstVerifyCalled = true;
+ return Task.CompletedTask;
+ });
+ settings.OnVerifyMismatch(
+ (receivedFile, verifiedFile) =>
+ {
+ onVerifyMismatchCalled = true;
+ return Task.CompletedTask;
+ });
+ await Assert.ThrowsAsync(() => Verify("value", settings));
+ Assert.True(onFirstVerifyCalled);
+ Assert.False(onVerifyMismatchCalled);
+ }
+
[Fact]
public Task ScrubTempPath()
{
diff --git a/src/Verify/Callbacks/FirstVerify.cs b/src/Verify/Callbacks/FirstVerify.cs
new file mode 100644
index 0000000000..bcf6a5060e
--- /dev/null
+++ b/src/Verify/Callbacks/FirstVerify.cs
@@ -0,0 +1,6 @@
+using System.Threading.Tasks;
+
+namespace Verify
+{
+ public delegate Task FirstVerify(string receivedFile);
+}
\ No newline at end of file
diff --git a/src/Verify/Callbacks/VerifyMismatch.cs b/src/Verify/Callbacks/VerifyMismatch.cs
new file mode 100644
index 0000000000..4fe9056485
--- /dev/null
+++ b/src/Verify/Callbacks/VerifyMismatch.cs
@@ -0,0 +1,6 @@
+using System.Threading.Tasks;
+
+namespace Verify
+{
+ public delegate Task VerifyMismatch(string receivedFile, string verifiedFile);
+}
\ No newline at end of file
diff --git a/src/Verify/Callbacks/VerifySettings.cs b/src/Verify/Callbacks/VerifySettings.cs
new file mode 100644
index 0000000000..f85a856c5d
--- /dev/null
+++ b/src/Verify/Callbacks/VerifySettings.cs
@@ -0,0 +1,21 @@
+namespace Verify
+{
+ public partial class VerifySettings
+ {
+ internal FirstVerify? handleOnFirstVerify;
+
+ public void OnFirstVerify(FirstVerify func)
+ {
+ Guard.AgainstNull(func, nameof(func));
+ handleOnFirstVerify = func;
+ }
+
+ internal VerifyMismatch? handleOnVerifyMismatch;
+
+ public void OnVerifyMismatch(VerifyMismatch func)
+ {
+ Guard.AgainstNull(func, nameof(func));
+ handleOnVerifyMismatch = func;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Verify/Verifier/VerifyEngine.cs b/src/Verify/Verifier/VerifyEngine.cs
index 1ac27dd906..dbd6de31f4 100644
--- a/src/Verify/Verifier/VerifyEngine.cs
+++ b/src/Verify/Verifier/VerifyEngine.cs
@@ -188,6 +188,10 @@ void ProcessEquals()
async Task ProcessNotEquals(StringBuilder builder, FilePair item)
{
+ if (settings.handleOnVerifyMismatch != null)
+ {
+ await settings.handleOnVerifyMismatch(item.Received, item.Verified);
+ }
builder.AppendLine($"{Path.GetFileName(item.Received)}");
if (Extensions.IsText(item.Extension))
{
@@ -239,6 +243,10 @@ async Task ProcessMissing(StringBuilder builder)
async Task ProcessMissing(StringBuilder builder, FilePair item)
{
+ if (settings.handleOnFirstVerify != null)
+ {
+ await settings.handleOnFirstVerify(item.Received);
+ }
builder.AppendLine($"{Path.GetFileName(item.Verified)}");
if (Extensions.IsText(item.Extension))
{
diff --git a/src/Verify/VerifySettings.cs b/src/Verify/VerifySettings.cs
index f2f3a587d1..a5d29797da 100644
--- a/src/Verify/VerifySettings.cs
+++ b/src/Verify/VerifySettings.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace Verify
{
@@ -21,6 +22,8 @@ public VerifySettings(VerifySettings? settingsToClone)
autoVerify = settingsToClone.autoVerify;
serialization = settingsToClone.serialization;
newLineEscapingDisabled = settingsToClone.newLineEscapingDisabled;
+ handleOnFirstVerify = settingsToClone.handleOnFirstVerify;
+ handleOnVerifyMismatch = settingsToClone.handleOnVerifyMismatch;
Namer = new Namer(settingsToClone.Namer);
foreach (var pair in settingsToClone.Data)
{