From ffe6713b5e1ff7ac99da9edbe15c37e37592f4ca Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sun, 21 Jan 2024 09:17:01 -0500 Subject: [PATCH] Add converter / utils tests --- src/MyWebLog.Data/Converters.fs | 36 ++++----- src/MyWebLog.Data/MyWebLog.Data.fsproj | 8 +- src/MyWebLog.Data/Utils.fs | 22 ++---- src/MyWebLog.Tests/ConvertersTests.fs | 31 ++++++++ src/MyWebLog.Tests/MyWebLog.Tests.fsproj | 1 + src/MyWebLog.Tests/Program.fs | 2 +- src/MyWebLog.Tests/UtilsTests.fs | 96 ++++++++++++++++++++++++ 7 files changed, 161 insertions(+), 35 deletions(-) create mode 100644 src/MyWebLog.Tests/UtilsTests.fs diff --git a/src/MyWebLog.Data/Converters.fs b/src/MyWebLog.Data/Converters.fs index b4e07a1..ad14d54 100644 --- a/src/MyWebLog.Data/Converters.fs +++ b/src/MyWebLog.Data/Converters.fs @@ -135,24 +135,24 @@ module Json = /// Configure a serializer to use these converters let configure (ser : JsonSerializer) = // Our converters - [ CategoryIdConverter() :> JsonConverter - CommentIdConverter() - CommentStatusConverter() - CustomFeedIdConverter() - CustomFeedSourceConverter() - ExplicitRatingConverter() - MarkupTextConverter() - PermalinkConverter() - PageIdConverter() - PodcastMediumConverter() - PostIdConverter() - TagMapIdConverter() - ThemeAssetIdConverter() - ThemeIdConverter() - UploadIdConverter() - WebLogIdConverter() - WebLogUserIdConverter() - ] |> List.iter ser.Converters.Add + [ CategoryIdConverter() :> JsonConverter + CommentIdConverter() + CommentStatusConverter() + CustomFeedIdConverter() + CustomFeedSourceConverter() + ExplicitRatingConverter() + MarkupTextConverter() + PermalinkConverter() + PageIdConverter() + PodcastMediumConverter() + PostIdConverter() + TagMapIdConverter() + ThemeAssetIdConverter() + ThemeIdConverter() + UploadIdConverter() + WebLogIdConverter() + WebLogUserIdConverter() ] + |> List.iter ser.Converters.Add // NodaTime let _ = ser.ConfigureForNodaTime DateTimeZoneProviders.Tzdb // Handles DUs with no associated data, as well as option fields diff --git a/src/MyWebLog.Data/MyWebLog.Data.fsproj b/src/MyWebLog.Data/MyWebLog.Data.fsproj index 5c8082d..0aa40b8 100644 --- a/src/MyWebLog.Data/MyWebLog.Data.fsproj +++ b/src/MyWebLog.Data/MyWebLog.Data.fsproj @@ -42,7 +42,13 @@ - + + + + + + <_Parameter1>MyWebLog.Tests + diff --git a/src/MyWebLog.Data/Utils.fs b/src/MyWebLog.Data/Utils.fs index eb87162..3432d34 100644 --- a/src/MyWebLog.Data/Utils.fs +++ b/src/MyWebLog.Data/Utils.fs @@ -9,13 +9,13 @@ open MyWebLog.ViewModels let rec orderByHierarchy (cats: Category list) parentId slugBase parentNames = seq { for cat in cats |> List.filter (fun c -> c.ParentId = parentId) do let fullSlug = (match slugBase with Some it -> $"{it}/" | None -> "") + cat.Slug - { Id = string cat.Id - Slug = fullSlug - Name = cat.Name - Description = cat.Description - ParentNames = Array.ofList parentNames - // Post counts are filled on a second pass - PostCount = 0 } + { Id = string cat.Id + Slug = fullSlug + Name = cat.Name + Description = cat.Description + ParentNames = Array.ofList parentNames + // Post counts are filled on a second pass + PostCount = 0 } yield! orderByHierarchy cats (Some cat.Id) (Some fullSlug) ([ cat.Name ] |> List.append parentNames) } @@ -24,14 +24,6 @@ let diffLists<'T, 'U when 'U: equality> oldItems newItems (f: 'T -> 'U) = let diff compList = fun item -> not (compList |> List.exists (fun other -> f item = f other)) List.filter (diff newItems) oldItems, List.filter (diff oldItems) newItems -/// Find meta items added and removed -let diffMetaItems (oldItems: MetaItem list) newItems = - diffLists oldItems newItems (fun item -> $"{item.Name}|{item.Value}") - -/// Find the permalinks added and removed -let diffPermalinks (oldLinks: Permalink list) newLinks = - diffLists oldLinks newLinks string - /// Find the revisions added and removed let diffRevisions (oldRevs: Revision list) newRevs = diffLists oldRevs newRevs (fun rev -> $"{rev.AsOf.ToUnixTimeTicks()}|{rev.Text}") diff --git a/src/MyWebLog.Tests/ConvertersTests.fs b/src/MyWebLog.Tests/ConvertersTests.fs index 3699943..3f9f053 100644 --- a/src/MyWebLog.Tests/ConvertersTests.fs +++ b/src/MyWebLog.Tests/ConvertersTests.fs @@ -1,6 +1,7 @@ module ConvertersTests open Expecto +open Microsoft.FSharpLu.Json open MyWebLog open MyWebLog.Converters.Json open Newtonsoft.Json @@ -243,6 +244,35 @@ let webLogUserIdConverterTests = testList "WebLogUserIdConverter" [ } ] +open NodaTime.Serialization.JsonNet + +/// Unit tests for the Json.configure function +let configureTests = test "Json.configure succeeds" { + let has typ (converter: JsonConverter) = converter.GetType() = typ + let ser = configure (JsonSerializer.Create()) + Expect.hasCountOf ser.Converters 1u (has typeof) "Category ID converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Comment ID converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Comment status converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Custom feed ID converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Custom feed source converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Explicit rating converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Markup text converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Permalink converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Page ID converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Podcast medium converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Post ID converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Tag map ID converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Theme asset ID converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Theme ID converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Upload ID converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Web log ID converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "Web log user ID converter not found" + Expect.hasCountOf ser.Converters 1u (has typeof) "F# type converter not found" + Expect.hasCountOf ser.Converters 1u (has (NodaConverters.InstantConverter.GetType())) "NodaTime converter not found" + Expect.equal ser.NullValueHandling NullValueHandling.Ignore "Null handling set incorrectly" + Expect.equal ser.MissingMemberHandling MissingMemberHandling.Ignore "Missing member handling set incorrectly" +} + /// All tests for the Data.Converters file let all = testList "Converters" [ categoryIdConverterTests @@ -262,4 +292,5 @@ let all = testList "Converters" [ uploadIdConverterTests webLogIdConverterTests webLogUserIdConverterTests + configureTests ] diff --git a/src/MyWebLog.Tests/MyWebLog.Tests.fsproj b/src/MyWebLog.Tests/MyWebLog.Tests.fsproj index b33f3fd..a0433b0 100644 --- a/src/MyWebLog.Tests/MyWebLog.Tests.fsproj +++ b/src/MyWebLog.Tests/MyWebLog.Tests.fsproj @@ -9,6 +9,7 @@ + diff --git a/src/MyWebLog.Tests/Program.fs b/src/MyWebLog.Tests/Program.fs index 7db606f..eda78d1 100644 --- a/src/MyWebLog.Tests/Program.fs +++ b/src/MyWebLog.Tests/Program.fs @@ -2,7 +2,7 @@ let allTests = testList "MyWebLog" [ testList "Domain" [ SupportTypesTests.all; DataTypesTests.all; ViewModelsTests.all ] - testList "Data" [ ConvertersTests.all ] + testList "Data" [ ConvertersTests.all; UtilsTests.all ] ] [] diff --git a/src/MyWebLog.Tests/UtilsTests.fs b/src/MyWebLog.Tests/UtilsTests.fs new file mode 100644 index 0000000..9346e87 --- /dev/null +++ b/src/MyWebLog.Tests/UtilsTests.fs @@ -0,0 +1,96 @@ +module UtilsTests + +open Expecto +open MyWebLog +open MyWebLog.Data +open NodaTime + +/// Unit tests for the orderByHierarchy function +let orderByHierarchyTests = test "orderByHierarchy succeeds" { + let rawCats = + [ { Category.Empty with Id = CategoryId "a"; Name = "Audio"; Slug = "audio"; ParentId = Some (CategoryId "p") } + { Category.Empty with + Id = CategoryId "b" + Name = "Breaking" + Description = Some "Breaking News" + Slug = "breaking" + ParentId = Some (CategoryId "n") } + { Category.Empty with Id = CategoryId "l"; Name = "Local"; Slug = "local"; ParentId = Some (CategoryId "b") } + { Category.Empty with Id = CategoryId "n"; Name = "News"; Slug = "news" } + { Category.Empty with Id = CategoryId "p"; Name = "Podcast"; Slug = "podcast" } + { Category.Empty with Id = CategoryId "v"; Name = "Video"; Slug = "vid"; ParentId = Some (CategoryId "p") } ] + let cats = Utils.orderByHierarchy rawCats None None [] |> List.ofSeq + Expect.equal cats.Length 6 "There should have been 6 categories" + Expect.equal cats[0].Id "n" "The first top-level category should have been News" + Expect.equal cats[0].Slug "news" "Slug for News not filled properly" + Expect.isEmpty cats[0].ParentNames "Parent names for News not filled properly" + Expect.equal cats[1].Id "b" "Breaking should have been just below News" + Expect.equal cats[1].Slug "news/breaking" "Slug for Breaking not filled properly" + Expect.equal cats[1].Name "Breaking" "Name not filled properly" + Expect.equal cats[1].Description (Some "Breaking News") "Description not filled properly" + Expect.equal cats[1].ParentNames [| "News" |] "Parent names for Breaking not filled properly" + Expect.equal cats[2].Id "l" "Local should have been just below Breaking" + Expect.equal cats[2].Slug "news/breaking/local" "Slug for Local not filled properly" + Expect.equal cats[2].ParentNames [| "News"; "Breaking" |] "Parent names for Local not filled properly" + Expect.equal cats[3].Id "p" "Podcast should have been the next top-level category" + Expect.equal cats[3].Slug "podcast" "Slug for Podcast not filled properly" + Expect.isEmpty cats[3].ParentNames "Parent names for Podcast not filled properly" + Expect.equal cats[4].Id "a" "Audio should have been just below Podcast" + Expect.equal cats[4].Slug "podcast/audio" "Slug for Audio not filled properly" + Expect.equal cats[4].ParentNames [| "Podcast" |] "Parent names for Audio not filled properly" + Expect.equal cats[5].Id "v" "Video should have been below Audio" + Expect.equal cats[5].Slug "podcast/vid" "Slug for Video not filled properly" + Expect.equal cats[5].ParentNames [| "Podcast" |] "Parent names for Video not filled properly" + Expect.hasCountOf cats 6u (fun it -> it.PostCount = 0) "All post counts should have been 0" +} + +/// Unit tests for the diffLists function +let diffListsTests = testList "diffLists" [ + test "succeeds with identical lists" { + let removed, added = Utils.diffLists [ 1; 2; 3 ] [ 1; 2; 3 ] id + Expect.isEmpty removed "There should have been no removed items returned" + Expect.isEmpty added "There should have been no added items returned" + } + test "succeeds with differing lists" { + let removed, added = Utils.diffLists [ 1; 2; 3 ] [ 3; 4; 5 ] string + Expect.equal removed [ 1; 2 ] "Removed items incorrect" + Expect.equal added [ 4; 5 ] "Added items incorrect" + } +] + +/// Unit tests for the diffRevisions function +let diffRevisionsTests = testList "diffRevisions" [ + test "succeeds with identical lists" { + let oldItems = + [ { AsOf = Noda.epoch + Duration.FromDays 3; Text = Html "

test" } + { AsOf = Noda.epoch; Text = Html "

test test" } ] + let newItems = + [ { AsOf = Noda.epoch; Text = Html "

test test" } + { AsOf = Noda.epoch + Duration.FromDays 3; Text = Html "

test" } ] + let removed, added = Utils.diffRevisions oldItems newItems + Expect.isEmpty removed "There should have been no removed items returned" + Expect.isEmpty added "There should have been no added items returned" + } + test "succeeds with differing lists" { + let oldItems = + [ { AsOf = Noda.epoch + Duration.FromDays 3; Text = Html "

test" } + { AsOf = Noda.epoch + Duration.FromDays 2; Text = Html "

tests" } + { AsOf = Noda.epoch; Text = Html "

test test" } ] + let newItems = + [ { AsOf = Noda.epoch + Duration.FromDays 4; Text = Html "

tests" } + { AsOf = Noda.epoch + Duration.FromDays 3; Text = Html "

test" } + { AsOf = Noda.epoch; Text = Html "

test test" } ] + let removed, added = Utils.diffRevisions oldItems newItems + Expect.equal removed.Length 1 "There should be 1 removed item" + Expect.equal removed[0].AsOf (Noda.epoch + Duration.FromDays 2) "Expected removed item incorrect" + Expect.equal added.Length 1 "There should be 1 added item" + Expect.equal added[0].AsOf (Noda.epoch + Duration.FromDays 4) "Expected added item incorrect" + } +] + +/// All tests for the Utils file +let all = testList "Utils" [ + orderByHierarchyTests + diffListsTests + diffRevisionsTests +]