From c9230c24cebd5ebacae7eced66ee4fd599bbb5af Mon Sep 17 00:00:00 2001 From: Patrick Stevens <3138005+Smaug123@users.noreply.github.com> Date: Mon, 16 Jun 2025 00:36:50 +0100 Subject: [PATCH] Allow line number stability too (#1) --- WoofWare.Expect.Test/SimpleTest.fs | 11 +++++++++-- WoofWare.Expect/Library.fs | 14 +++++++------- WoofWare.Expect/SurfaceBaseline.txt | 4 ++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/WoofWare.Expect.Test/SimpleTest.fs b/WoofWare.Expect.Test/SimpleTest.fs index 545a548..c7a20dd 100644 --- a/WoofWare.Expect.Test/SimpleTest.fs +++ b/WoofWare.Expect.Test/SimpleTest.fs @@ -17,7 +17,7 @@ module SimpleTest = let ``Example of a failing test`` () = expect { snapshot - "snapshot mismatch! snapshot at filepath.fs:32 (Example of a failing test) was: + "snapshot mismatch! snapshot at filepath.fs:99 (Example of a failing test) was: - 123 @@ -28,10 +28,17 @@ actual was: return Assert .Throws(fun () -> - expectWithMockedFilePath "filepath.fs" { + expectWithMockedFilePath ("filepath.fs", 99) { snapshot "123" return 124 } ) .Message } + + [] + let ``Basic example`` () = + expect { + snapshot "123" + return 123 + } diff --git a/WoofWare.Expect/Library.fs b/WoofWare.Expect/Library.fs index 12cec80..58641f3 100644 --- a/WoofWare.Expect/Library.fs +++ b/WoofWare.Expect/Library.fs @@ -32,8 +32,8 @@ module private Text = /// The builder which powers WoofWare.Expect. /// /// You're not expected to construct this explicitly; it's a computation expression, available as Builder.expect. -/// Override the file paths reported in snapshots, so that your tests can be fully stable even on failure. (You almost certainly don't want to set this.) -type ExpectBuilder (?filePathOverride : string) = +/// Override the file path and line numbers reported in snapshots, so that your tests can be fully stable even on failure. (You almost certainly don't want to set this.) +type ExpectBuilder (?sourceOverride : string * int) = /// Combine two `ExpectState`s. The first one is the "expected" snapshot; the second is the "actual". member _.Bind (state : ExpectState, f : unit -> ExpectState<'U>) : ExpectState<'U> = let actual = f () @@ -153,8 +153,8 @@ type ExpectBuilder (?filePathOverride : string) = if not (JsonElement.DeepEquals (canonicalActual.RootElement, canonicalSnapshot.RootElement)) then failwithf "snapshot mismatch! snapshot at %s:%i (%s) was:\n\n%s\n\nactual was:\n\n%s" - (filePathOverride |> Option.defaultValue source.FilePath) - source.LineNumber + (sourceOverride |> Option.map fst |> Option.defaultValue source.FilePath) + (sourceOverride |> Option.map snd |> Option.defaultValue source.LineNumber) source.MemberName (canonicalSnapshot.RootElement.ToString () |> Text.predent '-') (canonicalActual.RootElement.ToString () |> Text.predent '-') @@ -165,8 +165,8 @@ type ExpectBuilder (?filePathOverride : string) = if actual <> snapshot then failwithf "snapshot mismatch! snapshot at %s:%i (%s) was:\n\n%s\n\nactual was:\n\n%s" - (filePathOverride |> Option.defaultValue source.FilePath) - source.LineNumber + (sourceOverride |> Option.map fst |> Option.defaultValue source.FilePath) + (sourceOverride |> Option.map snd |> Option.defaultValue source.LineNumber) source.MemberName (snapshot |> Text.predent '-') (actual |> Text.predent '+') @@ -200,4 +200,4 @@ module Builder = /// You probably don't want to use this; use `expect` instead. /// The point of the mocked builder is to allow fully predictable testing of the WoofWare.Expect library itself. /// - let expectWithMockedFilePath (path : string) = ExpectBuilder path + let expectWithMockedFilePath (path : string, line : int) = ExpectBuilder ((path, line)) diff --git a/WoofWare.Expect/SurfaceBaseline.txt b/WoofWare.Expect/SurfaceBaseline.txt index 0312b42..06fe417 100644 --- a/WoofWare.Expect/SurfaceBaseline.txt +++ b/WoofWare.Expect/SurfaceBaseline.txt @@ -1,9 +1,9 @@ WoofWare.Expect.Builder inherit obj WoofWare.Expect.Builder.expect [static property]: [read-only] WoofWare.Expect.ExpectBuilder -WoofWare.Expect.Builder.expectWithMockedFilePath [static method]: string -> WoofWare.Expect.ExpectBuilder +WoofWare.Expect.Builder.expectWithMockedFilePath [static method]: (string, int) -> WoofWare.Expect.ExpectBuilder WoofWare.Expect.Builder.get_expect [static method]: unit -> WoofWare.Expect.ExpectBuilder WoofWare.Expect.ExpectBuilder inherit obj -WoofWare.Expect.ExpectBuilder..ctor [constructor]: string option +WoofWare.Expect.ExpectBuilder..ctor [constructor]: (string * int) option WoofWare.Expect.ExpectBuilder.Bind [method]: (unit WoofWare.Expect.ExpectState, unit -> 'U WoofWare.Expect.ExpectState) -> 'U WoofWare.Expect.ExpectState WoofWare.Expect.ExpectBuilder.Delay [method]: (unit -> 'T WoofWare.Expect.ExpectState) -> (unit -> 'T WoofWare.Expect.ExpectState) WoofWare.Expect.ExpectBuilder.Return [method]: 'T -> 'T WoofWare.Expect.ExpectState