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) {