Version 2.1 #41

Merged
danieljsummers merged 123 commits from version-2.1 into main 2024-03-27 00:13:28 +00:00
4 changed files with 878 additions and 722 deletions
Showing only changes of commit 29167eca6c - Show all commits

View File

@ -4,87 +4,84 @@ open Expecto
open MyWebLog open MyWebLog
/// Unit tests for the WebLog type /// Unit tests for the WebLog type
let webLogTests = let webLogTests = testList "WebLog" [
testList "WebLog" [ testList "ExtraPath" [
testList "ExtraPath" [ test "succeeds for blank URL base" {
test "succeeds for blank URL base" { Expect.equal WebLog.Empty.ExtraPath "" "Extra path should have been blank for blank URL base"
Expect.equal WebLog.Empty.ExtraPath "" "Extra path should have been blank for blank URL base" }
} test "succeeds for domain root URL" {
test "succeeds for domain root URL" { Expect.equal
Expect.equal { WebLog.Empty with UrlBase = "https://example.com" }.ExtraPath
{ WebLog.Empty with UrlBase = "https://example.com" }.ExtraPath ""
"" "Extra path should have been blank for domain root"
"Extra path should have been blank for domain root" }
} test "succeeds for single subdirectory" {
test "succeeds for single subdirectory" { Expect.equal
Expect.equal { WebLog.Empty with UrlBase = "https://a.com/sub" }.ExtraPath
{ WebLog.Empty with UrlBase = "https://a.com/sub" }.ExtraPath "/sub"
"/sub" "Extra path incorrect for a single subdirectory"
"Extra path incorrect for a single subdirectory" }
} test "succeeds for deeper nesting" {
test "succeeds for deeper nesting" { Expect.equal
Expect.equal { WebLog.Empty with UrlBase = "https://b.com/users/test/units" }.ExtraPath
{ WebLog.Empty with UrlBase = "https://b.com/users/test/units" }.ExtraPath "/users/test/units"
"/users/test/units" "Extra path incorrect for deeper nesting"
"Extra path incorrect for deeper nesting"
}
]
test "AbsoluteUrl succeeds" {
Expect.equal
({ WebLog.Empty with UrlBase = "https://my.site" }.AbsoluteUrl(Permalink "blog/page.html"))
"https://my.site/blog/page.html"
"Absolute URL is incorrect"
} }
testList "RelativeUrl" [
test "succeeds for domain root URL" {
Expect.equal
({ WebLog.Empty with UrlBase = "https://test.me" }.RelativeUrl(Permalink "about.htm"))
"/about.htm"
"Relative URL is incorrect for domain root site"
}
test "succeeds for domain non-root URL" {
Expect.equal
({ WebLog.Empty with UrlBase = "https://site.page/a/b/c" }.RelativeUrl(Permalink "x/y/z"))
"/a/b/c/x/y/z"
"Relative URL is incorrect for domain non-root site"
}
]
testList "LocalTime" [
test "succeeds when no time zone is set" {
Expect.equal
(WebLog.Empty.LocalTime(Noda.epoch))
(Noda.epoch.ToDateTimeUtc())
"Reference should be UTC when no time zone is specified"
}
test "succeeds when time zone is set" {
Expect.equal
({ WebLog.Empty with TimeZone = "Etc/GMT-1" }.LocalTime(Noda.epoch))
(Noda.epoch.ToDateTimeUtc().AddHours 1)
"The time should have been adjusted by one hour"
}
]
] ]
test "AbsoluteUrl succeeds" {
Expect.equal
({ WebLog.Empty with UrlBase = "https://my.site" }.AbsoluteUrl(Permalink "blog/page.html"))
"https://my.site/blog/page.html"
"Absolute URL is incorrect"
}
testList "RelativeUrl" [
test "succeeds for domain root URL" {
Expect.equal
({ WebLog.Empty with UrlBase = "https://test.me" }.RelativeUrl(Permalink "about.htm"))
"/about.htm"
"Relative URL is incorrect for domain root site"
}
test "succeeds for domain non-root URL" {
Expect.equal
({ WebLog.Empty with UrlBase = "https://site.page/a/b/c" }.RelativeUrl(Permalink "x/y/z"))
"/a/b/c/x/y/z"
"Relative URL is incorrect for domain non-root site"
}
]
testList "LocalTime" [
test "succeeds when no time zone is set" {
Expect.equal
(WebLog.Empty.LocalTime(Noda.epoch))
(Noda.epoch.ToDateTimeUtc())
"Reference should be UTC when no time zone is specified"
}
test "succeeds when time zone is set" {
Expect.equal
({ WebLog.Empty with TimeZone = "Etc/GMT-1" }.LocalTime(Noda.epoch))
(Noda.epoch.ToDateTimeUtc().AddHours 1)
"The time should have been adjusted by one hour"
}
]
]
/// Unit tests for the WebLogUser type /// Unit tests for the WebLogUser type
let webLogUserTests = let webLogUserTests = testList "WebLogUser" [
testList "WebLogUser" [ testList "DisplayName" [
testList "DisplayName" [ test "succeeds when a preferred name is present" {
test "succeeds when a preferred name is present" { Expect.equal
Expect.equal { WebLogUser.Empty with
{ WebLogUser.Empty with FirstName = "Thomas"; PreferredName = "Tom"; LastName = "Tester" }.DisplayName
FirstName = "Thomas"; PreferredName = "Tom"; LastName = "Tester" }.DisplayName "Tom Tester"
"Tom Tester" "Display name incorrect when preferred name is present"
"Display name incorrect when preferred name is present" }
} test "succeeds when a preferred name is absent" {
test "succeeds when a preferred name is absent" { Expect.equal
Expect.equal { WebLogUser.Empty with FirstName = "Test"; LastName = "Units" }.DisplayName
{ WebLogUser.Empty with FirstName = "Test"; LastName = "Units" }.DisplayName "Test Units"
"Test Units" "Display name incorrect when preferred name is absent"
"Display name incorrect when preferred name is absent" }
}
]
] ]
]
/// All tests for the Domain.DataTypes file /// All tests for the Domain.DataTypes file
let all = let all = testList "DataTypes" [ webLogTests; webLogUserTests ]
testList "DataTypes" [ webLogTests; webLogUserTests ]

View File

@ -1,9 +1,8 @@
open Expecto open Expecto
let allTests = let allTests = testList "MyWebLog" [
testList testList "Domain" [ SupportTypesTests.all; DataTypesTests.all; ViewModelsTests.all ]
"MyWebLog" ]
[ testList "Domain" [ SupportTypesTests.all; DataTypesTests.all; ViewModelsTests.all ] ]
[<EntryPoint>] [<EntryPoint>]
let main args = runTestsWithCLIArgs [] args allTests let main args = runTestsWithCLIArgs [] args allTests

View File

@ -6,427 +6,410 @@ open MyWebLog
open NodaTime open NodaTime
/// Tests for the NodaTime-wrapping module /// Tests for the NodaTime-wrapping module
let nodaTests = let nodaTests = testList "Noda" [
testList "Noda" [ test "epoch succeeds" {
test "epoch succeeds" { Expect.equal
Expect.equal (Noda.epoch.ToDateTimeUtc())
(Noda.epoch.ToDateTimeUtc()) (DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc))
(DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)) "The Unix epoch value is not correct"
"The Unix epoch value is not correct" }
} test "toSecondsPrecision succeeds" {
test "toSecondsPrecision succeeds" { let testDate = Instant.FromDateTimeUtc(DateTime(1970, 1, 1, 0, 0, 0, 444, DateTimeKind.Utc))
let testDate = Instant.FromDateTimeUtc(DateTime(1970, 1, 1, 0, 0, 0, 444, DateTimeKind.Utc)) // testDate.
// testDate. Expect.equal
Expect.equal ((Noda.toSecondsPrecision testDate).ToDateTimeUtc())
((Noda.toSecondsPrecision testDate).ToDateTimeUtc()) (Noda.epoch.ToDateTimeUtc())
(Noda.epoch.ToDateTimeUtc()) "Instant value was not rounded to seconds precision"
"Instant value was not rounded to seconds precision" }
} test "fromDateTime succeeds" {
test "fromDateTime succeeds" { let testDate = DateTime(1970, 1, 1, 0, 0, 0, 444, DateTimeKind.Utc)
let testDate = DateTime(1970, 1, 1, 0, 0, 0, 444, DateTimeKind.Utc) Expect.equal (Noda.fromDateTime testDate) Noda.epoch "fromDateTime did not truncate to seconds"
Expect.equal (Noda.fromDateTime testDate) Noda.epoch "fromDateTime did not truncate to seconds" }
} ]
]
/// Tests for the AccessLevel type /// Tests for the AccessLevel type
let accessLevelTests = let accessLevelTests = testList "AccessLevel" [
testList "AccessLevel" [ testList "Parse" [
testList "Parse" [ test "succeeds for \"Author\"" {
test "succeeds for \"Author\"" { Expect.equal Author (AccessLevel.Parse "Author") "Author not parsed correctly"
Expect.equal Author (AccessLevel.Parse "Author") "Author not parsed correctly" }
} test "succeeds for \"Editor\"" {
test "succeeds for \"Editor\"" { Expect.equal Editor (AccessLevel.Parse "Editor") "Editor not parsed correctly"
Expect.equal Editor (AccessLevel.Parse "Editor") "Editor not parsed correctly" }
} test "succeeds for \"WebLogAdmin\"" {
test "succeeds for \"WebLogAdmin\"" { Expect.equal WebLogAdmin (AccessLevel.Parse "WebLogAdmin") "WebLogAdmin not parsed correctly"
Expect.equal WebLogAdmin (AccessLevel.Parse "WebLogAdmin") "WebLogAdmin not parsed correctly" }
} test "succeeds for \"Administrator\"" {
test "succeeds for \"Administrator\"" { Expect.equal Administrator (AccessLevel.Parse "Administrator") "Administrator not parsed correctly"
Expect.equal Administrator (AccessLevel.Parse "Administrator") "Administrator not parsed correctly" }
} test "fails when given an unrecognized value" {
test "fails when given an unrecognized value" { Expect.throwsT<ArgumentException>
Expect.throwsT<ArgumentException> (fun () -> ignore (AccessLevel.Parse "Hacker")) "Invalid value should have raised an exception"
(fun () -> ignore (AccessLevel.Parse "Hacker")) "Invalid value should have raised an exception"
}
]
testList "ToString" [
test "Author succeeds" {
Expect.equal (string Author) "Author" "Author string incorrect"
}
test "Editor succeeds" {
Expect.equal (string Editor) "Editor" "Editor string incorrect"
}
test "WebLogAdmin succeeds" {
Expect.equal (string WebLogAdmin) "WebLogAdmin" "WebLogAdmin string incorrect"
}
test "Administrator succeeds" {
Expect.equal (string Administrator) "Administrator" "Administrator string incorrect"
}
]
testList "HasAccess" [
test "Author has Author access" {
Expect.isTrue (Author.HasAccess Author) "Author should have Author access"
}
test "Author does not have Editor access" {
Expect.isFalse (Author.HasAccess Editor) "Author should not have Editor access"
}
test "Author does not have WebLogAdmin access" {
Expect.isFalse (Author.HasAccess WebLogAdmin) "Author should not have WebLogAdmin access"
}
test "Author does not have Administrator access" {
Expect.isFalse (Author.HasAccess Administrator) "Author should not have Administrator access"
}
test "Editor has Author access" {
Expect.isTrue (Editor.HasAccess Author) "Editor should have Author access"
}
test "Editor has Editor access" {
Expect.isTrue (Editor.HasAccess Editor) "Editor should have Editor access"
}
test "Editor does not have WebLogAdmin access" {
Expect.isFalse (Editor.HasAccess WebLogAdmin) "Editor should not have WebLogAdmin access"
}
test "Editor does not have Administrator access" {
Expect.isFalse (Editor.HasAccess Administrator) "Editor should not have Administrator access"
}
test "WebLogAdmin has Author access" {
Expect.isTrue (WebLogAdmin.HasAccess Author) "WebLogAdmin should have Author access"
}
test "WebLogAdmin has Editor access" {
Expect.isTrue (WebLogAdmin.HasAccess Editor) "WebLogAdmin should have Editor access"
}
test "WebLogAdmin has WebLogAdmin access" {
Expect.isTrue (WebLogAdmin.HasAccess WebLogAdmin) "WebLogAdmin should have WebLogAdmin access"
}
test "WebLogAdmin does not have Administrator access" {
Expect.isFalse (WebLogAdmin.HasAccess Administrator) "WebLogAdmin should not have Administrator access"
}
test "Administrator has Author access" {
Expect.isTrue (Administrator.HasAccess Author) "Administrator should have Author access"
}
test "Administrator has Editor access" {
Expect.isTrue (Administrator.HasAccess Editor) "Administrator should have Editor access"
}
test "Administrator has WebLogAdmin access" {
Expect.isTrue (Administrator.HasAccess WebLogAdmin) "Administrator should have WebLogAdmin access"
}
test "Administrator has Administrator access" {
Expect.isTrue (Administrator.HasAccess Administrator) "Administrator should have Administrator access"
}
]
]
/// Tests for the CommentStatus type
let commentStatusTests =
testList "CommentStatus" [
testList "Parse" [
test "succeeds for \"Approved\"" {
Expect.equal Approved (CommentStatus.Parse "Approved") "Approved not parsed correctly"
}
test "succeeds for \"Pending\"" {
Expect.equal Pending (CommentStatus.Parse "Pending") "Pending not parsed correctly"
}
test "succeeds for \"Spam\"" {
Expect.equal Spam (CommentStatus.Parse "Spam") "Spam not parsed correctly"
}
test "fails for unrecognized value" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (CommentStatus.Parse "Live")) "Invalid value should have raised an exception"
}
]
testList "ToString" [
test "Approved succeeds" {
Expect.equal (string Approved) "Approved" "Approved string incorrect"
}
test "Pending succeeds" {
Expect.equal (string Pending) "Pending" "Pending string incorrect"
}
test "Spam succeeds" {
Expect.equal (string Spam) "Spam" "Spam string incorrect"
}
]
]
let explicitRatingTests =
testList "ExplicitRating" [
testList "Parse" [
test "succeeds for \"yes\"" {
Expect.equal Yes (ExplicitRating.Parse "yes") "\"yes\" not parsed correctly"
}
test "succeeds for \"no\"" {
Expect.equal No (ExplicitRating.Parse "no") "\"no\" not parsed correctly"
}
test "succeeds for \"clean\"" {
Expect.equal Clean (ExplicitRating.Parse "clean") "\"clean\" not parsed correctly"
}
test "fails for unrecognized value" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (ExplicitRating.Parse "maybe")) "Invalid value should have raised an exception"
}
]
testList "ToString" [
test "Yes succeeds" {
Expect.equal (string Yes) "yes" "Yes string incorrect"
}
test "No succeeds" {
Expect.equal (string No) "no" "No string incorrect"
}
test "Clean succeeds" {
Expect.equal (string Clean) "clean" "Clean string incorrect"
}
]
]
/// Tests for the Episode type
let episodeTests =
testList "Episode" [
testList "FormatDuration" [
test "succeeds when no duration is specified" {
Expect.isNone (Episode.Empty.FormatDuration()) "A missing duration should have returned None"
}
test "succeeds when duration is specified" {
Expect.equal
({ Episode.Empty with
Duration = Some (Duration.FromMinutes 3L + Duration.FromSeconds 13L) }.FormatDuration())
(Some "0:03:13")
"Duration not formatted correctly"
}
test "succeeds when duration is > 10 hours" {
Expect.equal
({ Episode.Empty with Duration = Some (Duration.FromHours 11) }.FormatDuration())
(Some "11:00:00")
"Duration not formatted correctly"
}
]
]
/// Unit tests for the MarkupText type
let markupTextTests =
testList "MarkupText" [
testList "Parse" [
test "succeeds with HTML content" {
let txt = MarkupText.Parse "HTML: <p>howdy</p>"
match txt with
| Html it when it = "<p>howdy</p>" -> ()
| _ -> Expect.isTrue false $"Unexpected parse result for HTML: %A{txt}"
}
test "succeeds with Markdown content" {
let txt = MarkupText.Parse "Markdown: # A Title"
match txt with
| Markdown it when it = "# A Title" -> ()
| _ -> Expect.isTrue false $"Unexpected parse result for Markdown: %A{txt}"
}
test "fails with unexpected content" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (MarkupText.Parse "LaTEX: nope")) "Invalid value should have raised an exception"
}
]
testList "SourceType" [
test "succeeds for HTML" {
Expect.equal (MarkupText.Parse "HTML: something").SourceType "HTML" "HTML source type incorrect"
}
test "succeeds for Markdown" {
Expect.equal (MarkupText.Parse "Markdown: blah").SourceType "Markdown" "Markdown source type incorrect"
}
]
testList "Text" [
test "succeeds for HTML" {
Expect.equal (MarkupText.Parse "HTML: test").Text "test" "HTML text incorrect"
}
test "succeeds for Markdown" {
Expect.equal (MarkupText.Parse "Markdown: test!").Text "test!" "Markdown text incorrect"
}
]
testList "ToString" [
test "succeeds for HTML" {
Expect.equal
(string (MarkupText.Parse "HTML: <h1>HTML</h1>"))
"HTML: <h1>HTML</h1>"
"HTML string value incorrect"
}
test "succeeds for Markdown" {
Expect.equal
(string (MarkupText.Parse "Markdown: # Some Content"))
"Markdown: # Some Content"
"Markdown string value incorrect"
}
]
testList "AsHtml" [
test "succeeds for HTML" {
Expect.equal
((MarkupText.Parse "HTML: <h1>The Heading</h1>").AsHtml())
"<h1>The Heading</h1>"
"HTML value incorrect"
}
test "succeeds for Markdown" {
Expect.equal
((MarkupText.Parse "Markdown: *emphasis*").AsHtml())
"<p><em>emphasis</em></p>\n"
"Markdown HTML value incorrect"
}
]
]
/// Unit tests for the PodcastMedium type
let podcastMediumTests =
testList "PodcastMedium" [
testList "Parse" [
test "succeeds for \"podcast\"" {
Expect.equal (PodcastMedium.Parse "podcast") Podcast "\"podcast\" not parsed correctly"
}
test "succeeds for \"music\"" {
Expect.equal (PodcastMedium.Parse "music") Music "\"music\" not parsed correctly"
}
test "succeeds for \"video\"" {
Expect.equal (PodcastMedium.Parse "video") Video "\"video\" not parsed correctly"
}
test "succeeds for \"film\"" {
Expect.equal (PodcastMedium.Parse "film") Film "\"film\" not parsed correctly"
}
test "succeeds for \"audiobook\"" {
Expect.equal (PodcastMedium.Parse "audiobook") Audiobook "\"audiobook\" not parsed correctly"
}
test "succeeds for \"newsletter\"" {
Expect.equal (PodcastMedium.Parse "newsletter") Newsletter "\"newsletter\" not parsed correctly"
}
test "succeeds for \"blog\"" {
Expect.equal (PodcastMedium.Parse "blog") Blog "\"blog\" not parsed correctly"
}
test "fails for invalid type" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (PodcastMedium.Parse "laser")) "Invalid value should have raised an exception"
}
]
testList "ToString" [
test "succeeds for Podcast" {
Expect.equal (string Podcast) "podcast" "Podcast string incorrect"
}
test "succeeds for Music" {
Expect.equal (string Music) "music" "Music string incorrect"
}
test "succeeds for Video" {
Expect.equal (string Video) "video" "Video string incorrect"
}
test "succeeds for Film" {
Expect.equal (string Film) "film" "Film string incorrect"
}
test "succeeds for Audiobook" {
Expect.equal (string Audiobook) "audiobook" "Audiobook string incorrect"
}
test "succeeds for Newsletter" {
Expect.equal (string Newsletter) "newsletter" "Newsletter string incorrect"
}
test "succeeds for Blog" {
Expect.equal (string Blog) "blog" "Blog string incorrect"
}
]
]
/// Unit tests for the PostStatus type
let postStatusTests =
testList "PostStatus" [
testList "Parse" [
test "succeeds for \"Draft\"" {
Expect.equal (PostStatus.Parse "Draft") Draft "\"Draft\" not parsed correctly"
}
test "succeeds for \"Published\"" {
Expect.equal (PostStatus.Parse "Published") Published "\"Published\" not parsed correctly"
}
test "fails for unrecognized value" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (PostStatus.Parse "Rescinded")) "Invalid value should have raised an exception"
}
]
]
/// Unit tests for the CustomFeedSource type
let customFeedSourceTests =
testList "CustomFeedSource" [
testList "Parse" [
test "succeeds for category feeds" {
Expect.equal
(CustomFeedSource.Parse "category:abc123")
(Category (CategoryId "abc123"))
"Category feed not parsed correctly"
}
test "succeeds for tag feeds" {
Expect.equal (CustomFeedSource.Parse "tag:turtles") (Tag "turtles") "Tag feed not parsed correctly"
}
test "fails for unknown type" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (CustomFeedSource.Parse "nasa:sat1"))
"Invalid value should have raised an exception"
}
]
testList "ToString" [
test "succeeds for category feed" {
Expect.equal
(string (CustomFeedSource.Parse "category:fish")) "category:fish" "Category feed string incorrect"
}
test "succeeds for tag feed" {
Expect.equal (string (CustomFeedSource.Parse "tag:rocks")) "tag:rocks" "Tag feed string incorrect"
}
]
]
/// Unit tests for the ThemeAssetId type
let themeAssetIdTests =
testList "ThemeAssetId" [
testList "Parse" [
test "succeeds with expected values" {
Expect.equal
(ThemeAssetId.Parse "test-theme/the-asset")
(ThemeAssetId ((ThemeId "test-theme"), "the-asset"))
"Theme asset ID not parsed correctly"
}
test "fails if no slash is present" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (ThemeAssetId.Parse "my-theme-asset"))
"Invalid value should have raised an exception"
}
]
test "ToString succeeds" {
Expect.equal
(string (ThemeAssetId ((ThemeId "howdy"), "pardner"))) "howdy/pardner" "Theme asset ID string incorrect"
} }
] ]
testList "ToString" [
test "Author succeeds" {
Expect.equal (string Author) "Author" "Author string incorrect"
}
test "Editor succeeds" {
Expect.equal (string Editor) "Editor" "Editor string incorrect"
}
test "WebLogAdmin succeeds" {
Expect.equal (string WebLogAdmin) "WebLogAdmin" "WebLogAdmin string incorrect"
}
test "Administrator succeeds" {
Expect.equal (string Administrator) "Administrator" "Administrator string incorrect"
}
]
testList "HasAccess" [
test "Author has Author access" {
Expect.isTrue (Author.HasAccess Author) "Author should have Author access"
}
test "Author does not have Editor access" {
Expect.isFalse (Author.HasAccess Editor) "Author should not have Editor access"
}
test "Author does not have WebLogAdmin access" {
Expect.isFalse (Author.HasAccess WebLogAdmin) "Author should not have WebLogAdmin access"
}
test "Author does not have Administrator access" {
Expect.isFalse (Author.HasAccess Administrator) "Author should not have Administrator access"
}
test "Editor has Author access" {
Expect.isTrue (Editor.HasAccess Author) "Editor should have Author access"
}
test "Editor has Editor access" {
Expect.isTrue (Editor.HasAccess Editor) "Editor should have Editor access"
}
test "Editor does not have WebLogAdmin access" {
Expect.isFalse (Editor.HasAccess WebLogAdmin) "Editor should not have WebLogAdmin access"
}
test "Editor does not have Administrator access" {
Expect.isFalse (Editor.HasAccess Administrator) "Editor should not have Administrator access"
}
test "WebLogAdmin has Author access" {
Expect.isTrue (WebLogAdmin.HasAccess Author) "WebLogAdmin should have Author access"
}
test "WebLogAdmin has Editor access" {
Expect.isTrue (WebLogAdmin.HasAccess Editor) "WebLogAdmin should have Editor access"
}
test "WebLogAdmin has WebLogAdmin access" {
Expect.isTrue (WebLogAdmin.HasAccess WebLogAdmin) "WebLogAdmin should have WebLogAdmin access"
}
test "WebLogAdmin does not have Administrator access" {
Expect.isFalse (WebLogAdmin.HasAccess Administrator) "WebLogAdmin should not have Administrator access"
}
test "Administrator has Author access" {
Expect.isTrue (Administrator.HasAccess Author) "Administrator should have Author access"
}
test "Administrator has Editor access" {
Expect.isTrue (Administrator.HasAccess Editor) "Administrator should have Editor access"
}
test "Administrator has WebLogAdmin access" {
Expect.isTrue (Administrator.HasAccess WebLogAdmin) "Administrator should have WebLogAdmin access"
}
test "Administrator has Administrator access" {
Expect.isTrue (Administrator.HasAccess Administrator) "Administrator should have Administrator access"
}
]
]
/// Tests for the CommentStatus type
let commentStatusTests = testList "CommentStatus" [
testList "Parse" [
test "succeeds for \"Approved\"" {
Expect.equal Approved (CommentStatus.Parse "Approved") "Approved not parsed correctly"
}
test "succeeds for \"Pending\"" {
Expect.equal Pending (CommentStatus.Parse "Pending") "Pending not parsed correctly"
}
test "succeeds for \"Spam\"" {
Expect.equal Spam (CommentStatus.Parse "Spam") "Spam not parsed correctly"
}
test "fails for unrecognized value" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (CommentStatus.Parse "Live")) "Invalid value should have raised an exception"
}
]
testList "ToString" [
test "Approved succeeds" {
Expect.equal (string Approved) "Approved" "Approved string incorrect"
}
test "Pending succeeds" {
Expect.equal (string Pending) "Pending" "Pending string incorrect"
}
test "Spam succeeds" {
Expect.equal (string Spam) "Spam" "Spam string incorrect"
}
]
]
/// Tests for the ExplicitRating type
let explicitRatingTests = testList "ExplicitRating" [
testList "Parse" [
test "succeeds for \"yes\"" {
Expect.equal Yes (ExplicitRating.Parse "yes") "\"yes\" not parsed correctly"
}
test "succeeds for \"no\"" {
Expect.equal No (ExplicitRating.Parse "no") "\"no\" not parsed correctly"
}
test "succeeds for \"clean\"" {
Expect.equal Clean (ExplicitRating.Parse "clean") "\"clean\" not parsed correctly"
}
test "fails for unrecognized value" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (ExplicitRating.Parse "maybe")) "Invalid value should have raised an exception"
}
]
testList "ToString" [
test "Yes succeeds" {
Expect.equal (string Yes) "yes" "Yes string incorrect"
}
test "No succeeds" {
Expect.equal (string No) "no" "No string incorrect"
}
test "Clean succeeds" {
Expect.equal (string Clean) "clean" "Clean string incorrect"
}
]
]
/// Tests for the Episode type
let episodeTests = testList "Episode" [
testList "FormatDuration" [
test "succeeds when no duration is specified" {
Expect.isNone (Episode.Empty.FormatDuration()) "A missing duration should have returned None"
}
test "succeeds when duration is specified" {
Expect.equal
({ Episode.Empty with
Duration = Some (Duration.FromMinutes 3L + Duration.FromSeconds 13L) }.FormatDuration())
(Some "0:03:13")
"Duration not formatted correctly"
}
test "succeeds when duration is > 10 hours" {
Expect.equal
({ Episode.Empty with Duration = Some (Duration.FromHours 11) }.FormatDuration())
(Some "11:00:00")
"Duration not formatted correctly"
}
]
]
/// Unit tests for the MarkupText type
let markupTextTests = testList "MarkupText" [
testList "Parse" [
test "succeeds with HTML content" {
let txt = MarkupText.Parse "HTML: <p>howdy</p>"
match txt with
| Html it when it = "<p>howdy</p>" -> ()
| _ -> Expect.isTrue false $"Unexpected parse result for HTML: %A{txt}"
}
test "succeeds with Markdown content" {
let txt = MarkupText.Parse "Markdown: # A Title"
match txt with
| Markdown it when it = "# A Title" -> ()
| _ -> Expect.isTrue false $"Unexpected parse result for Markdown: %A{txt}"
}
test "fails with unexpected content" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (MarkupText.Parse "LaTEX: nope")) "Invalid value should have raised an exception"
}
]
testList "SourceType" [
test "succeeds for HTML" {
Expect.equal (MarkupText.Parse "HTML: something").SourceType "HTML" "HTML source type incorrect"
}
test "succeeds for Markdown" {
Expect.equal (MarkupText.Parse "Markdown: blah").SourceType "Markdown" "Markdown source type incorrect"
}
]
testList "Text" [
test "succeeds for HTML" {
Expect.equal (MarkupText.Parse "HTML: test").Text "test" "HTML text incorrect"
}
test "succeeds for Markdown" {
Expect.equal (MarkupText.Parse "Markdown: test!").Text "test!" "Markdown text incorrect"
}
]
testList "ToString" [
test "succeeds for HTML" {
Expect.equal
(string (MarkupText.Parse "HTML: <h1>HTML</h1>")) "HTML: <h1>HTML</h1>" "HTML string value incorrect"
}
test "succeeds for Markdown" {
Expect.equal
(string (MarkupText.Parse "Markdown: # Some Content"))
"Markdown: # Some Content"
"Markdown string value incorrect"
}
]
testList "AsHtml" [
test "succeeds for HTML" {
Expect.equal
((MarkupText.Parse "HTML: <h1>The Heading</h1>").AsHtml()) "<h1>The Heading</h1>" "HTML value incorrect"
}
test "succeeds for Markdown" {
Expect.equal
((MarkupText.Parse "Markdown: *emphasis*").AsHtml())
"<p><em>emphasis</em></p>\n"
"Markdown HTML value incorrect"
}
]
]
/// Unit tests for the PodcastMedium type
let podcastMediumTests = testList "PodcastMedium" [
testList "Parse" [
test "succeeds for \"podcast\"" {
Expect.equal (PodcastMedium.Parse "podcast") Podcast "\"podcast\" not parsed correctly"
}
test "succeeds for \"music\"" {
Expect.equal (PodcastMedium.Parse "music") Music "\"music\" not parsed correctly"
}
test "succeeds for \"video\"" {
Expect.equal (PodcastMedium.Parse "video") Video "\"video\" not parsed correctly"
}
test "succeeds for \"film\"" {
Expect.equal (PodcastMedium.Parse "film") Film "\"film\" not parsed correctly"
}
test "succeeds for \"audiobook\"" {
Expect.equal (PodcastMedium.Parse "audiobook") Audiobook "\"audiobook\" not parsed correctly"
}
test "succeeds for \"newsletter\"" {
Expect.equal (PodcastMedium.Parse "newsletter") Newsletter "\"newsletter\" not parsed correctly"
}
test "succeeds for \"blog\"" {
Expect.equal (PodcastMedium.Parse "blog") Blog "\"blog\" not parsed correctly"
}
test "fails for invalid type" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (PodcastMedium.Parse "laser")) "Invalid value should have raised an exception"
}
]
testList "ToString" [
test "succeeds for Podcast" {
Expect.equal (string Podcast) "podcast" "Podcast string incorrect"
}
test "succeeds for Music" {
Expect.equal (string Music) "music" "Music string incorrect"
}
test "succeeds for Video" {
Expect.equal (string Video) "video" "Video string incorrect"
}
test "succeeds for Film" {
Expect.equal (string Film) "film" "Film string incorrect"
}
test "succeeds for Audiobook" {
Expect.equal (string Audiobook) "audiobook" "Audiobook string incorrect"
}
test "succeeds for Newsletter" {
Expect.equal (string Newsletter) "newsletter" "Newsletter string incorrect"
}
test "succeeds for Blog" {
Expect.equal (string Blog) "blog" "Blog string incorrect"
}
]
]
/// Unit tests for the PostStatus type
let postStatusTests = testList "PostStatus" [
testList "Parse" [
test "succeeds for \"Draft\"" {
Expect.equal (PostStatus.Parse "Draft") Draft "\"Draft\" not parsed correctly"
}
test "succeeds for \"Published\"" {
Expect.equal (PostStatus.Parse "Published") Published "\"Published\" not parsed correctly"
}
test "fails for unrecognized value" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (PostStatus.Parse "Rescinded")) "Invalid value should have raised an exception"
}
]
]
/// Unit tests for the CustomFeedSource type
let customFeedSourceTests = testList "CustomFeedSource" [
testList "Parse" [
test "succeeds for category feeds" {
Expect.equal
(CustomFeedSource.Parse "category:abc123")
(Category (CategoryId "abc123"))
"Category feed not parsed correctly"
}
test "succeeds for tag feeds" {
Expect.equal (CustomFeedSource.Parse "tag:turtles") (Tag "turtles") "Tag feed not parsed correctly"
}
test "fails for unknown type" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (CustomFeedSource.Parse "nasa:sat1")) "Invalid value should have raised an exception"
}
]
testList "ToString" [
test "succeeds for category feed" {
Expect.equal
(string (CustomFeedSource.Parse "category:fish")) "category:fish" "Category feed string incorrect"
}
test "succeeds for tag feed" {
Expect.equal (string (CustomFeedSource.Parse "tag:rocks")) "tag:rocks" "Tag feed string incorrect"
}
]
]
/// Unit tests for the ThemeAssetId type
let themeAssetIdTests = testList "ThemeAssetId" [
testList "Parse" [
test "succeeds with expected values" {
Expect.equal
(ThemeAssetId.Parse "test-theme/the-asset")
(ThemeAssetId ((ThemeId "test-theme"), "the-asset"))
"Theme asset ID not parsed correctly"
}
test "fails if no slash is present" {
Expect.throwsT<ArgumentException>
(fun () -> ignore (ThemeAssetId.Parse "my-theme-asset")) "Invalid value should have raised an exception"
}
]
test "ToString succeeds" {
Expect.equal
(string (ThemeAssetId ((ThemeId "howdy"), "pardner"))) "howdy/pardner" "Theme asset ID string incorrect"
}
]
/// Unit tests for the UploadDestination type /// Unit tests for the UploadDestination type
let uploadDestinationTests = let uploadDestinationTests = testList "UploadDestination" [
testList "UploadDestination" [ testList "Parse" [
testList "Parse" [ test "succeeds for \"Database\"" {
test "succeeds for \"Database\"" { Expect.equal (UploadDestination.Parse "Database") Database "\"Database\" not parsed correctly"
Expect.equal (UploadDestination.Parse "Database") Database "\"Database\" not parsed correctly" }
} test "succeeds for \"Disk\"" {
test "succeeds for \"Disk\"" { Expect.equal (UploadDestination.Parse "Disk") Disk "\"Disk\" not parsed correctly"
Expect.equal (UploadDestination.Parse "Disk") Disk "\"Disk\" not parsed correctly" }
} test "fails for unrecognized value" {
test "fails for unrecognized value" { Expect.throwsT<ArgumentException>
Expect.throwsT<ArgumentException> (fun () -> ignore (UploadDestination.Parse "Azure")) "Invalid value should have raised an exception"
(fun () -> ignore (UploadDestination.Parse "Azure")) "Invalid value should have raised an exception" }
}
]
testList "ToString" [
test "succeeds for Database" {
Expect.equal (string Database) "Database" "Database string incorrect"
}
test "succeeds for Disk" {
Expect.equal (string Disk) "Disk" "Disk string incorrect"
}
]
] ]
testList "ToString" [
test "succeeds for Database" {
Expect.equal (string Database) "Database" "Database string incorrect"
}
test "succeeds for Disk" {
Expect.equal (string Disk) "Disk" "Disk string incorrect"
}
]
]
/// All tests for the Domain.SupportTypes file /// All tests for the Domain.SupportTypes file
let all = let all = testList "SupportTypes" [
testList nodaTests
"SupportTypes" accessLevelTests
[ nodaTests commentStatusTests
accessLevelTests explicitRatingTests
commentStatusTests episodeTests
explicitRatingTests markupTextTests
episodeTests podcastMediumTests
markupTextTests postStatusTests
podcastMediumTests customFeedSourceTests
postStatusTests themeAssetIdTests
customFeedSourceTests uploadDestinationTests
themeAssetIdTests ]
uploadDestinationTests ]

View File

@ -7,205 +7,195 @@ open MyWebLog.ViewModels
open NodaTime open NodaTime
/// Unit tests for the addBaseToRelativeUrls helper function /// Unit tests for the addBaseToRelativeUrls helper function
let addBaseToRelativeUrlsTests = let addBaseToRelativeUrlsTests = testList "PublicHelpers.addBaseToRelativeUrls" [
testList "PublicHelpers.addBaseToRelativeUrls" [ test "succeeds when there is no extra URL path" {
test "succeeds when there is no extra URL path" { let testText = """<a href="/somewhere-else.html">Howdy></a>"""
let testText = """<a href="/somewhere-else.html">Howdy></a>""" let modified = addBaseToRelativeUrls "" testText
let modified = addBaseToRelativeUrls "" testText Expect.equal modified testText "The text should not have been modified"
Expect.equal modified testText "The text should not have been modified" }
} test "succeeds with an extra URL path" {
test "succeeds with an extra URL path" { let testText =
let testText = """<a href="/my-link.htm"><img src="/pretty-picture.jpg"></a><a href="https://example.com>link</a>"""
"""<a href="/my-link.htm"><img src="/pretty-picture.jpg"></a><a href="https://example.com>link</a>""" let expected =
let expected = """<a href="/a/b/my-link.htm"><img src="/a/b/pretty-picture.jpg"></a><a href="https://example.com>link</a>"""
"""<a href="/a/b/my-link.htm"><img src="/a/b/pretty-picture.jpg"></a><a href="https://example.com>link</a>""" Expect.equal (addBaseToRelativeUrls "/a/b" testText) expected "Relative URLs not modified correctly"
Expect.equal (addBaseToRelativeUrls "/a/b" testText) expected "Relative URLs not modified correctly" }
} ]
]
/// Unit tests for the DisplayCustomFeed type /// Unit tests for the DisplayCustomFeed type
let displayCustomFeedTests = let displayCustomFeedTests = testList "DisplayCustomFeed.FromFeed" [
testList "DisplayCustomFeed.FromFeed" [ test "succeeds for a feed for an existing category" {
test "succeeds for a feed for an existing category" { let cats =
let cats = [| { DisplayCategory.Id = "abc"
[| { DisplayCategory.Id = "abc" Slug = "a-b-c"
Slug = "a-b-c" Name = "My Lovely Category"
Name = "My Lovely Category" Description = None
Description = None ParentNames = [||]
ParentNames = [||] PostCount = 3 } |]
PostCount = 3 } |] let feed =
let feed = { CustomFeed.Empty with
{ CustomFeed.Empty with Id = CustomFeedId "test-feed"
Id = CustomFeedId "test-feed" Source = Category (CategoryId "abc")
Source = Category (CategoryId "abc") Path = Permalink "test-feed.xml" }
Path = Permalink "test-feed.xml" } let model = DisplayCustomFeed.FromFeed cats feed
let model = DisplayCustomFeed.FromFeed cats feed Expect.equal model.Id "test-feed" "Id not filled properly"
Expect.equal model.Id "test-feed" "Id not filled properly" Expect.equal model.Source "Category: My Lovely Category" "Source not filled properly"
Expect.equal model.Source "Category: My Lovely Category" "Source not filled properly" Expect.equal model.Path "test-feed.xml" "Path not filled properly"
Expect.equal model.Path "test-feed.xml" "Path not filled properly" Expect.isFalse model.IsPodcast "IsPodcast not filled properly"
Expect.isFalse model.IsPodcast "IsPodcast not filled properly" }
} test "succeeds for a feed for a non-existing category" {
test "succeeds for a feed for a non-existing category" { let feed =
let feed = { CustomFeed.Empty with
{ CustomFeed.Empty with Id = CustomFeedId "bad-feed"
Id = CustomFeedId "bad-feed" Source = Category (CategoryId "xyz")
Source = Category (CategoryId "xyz") Path = Permalink "trouble.xml" }
Path = Permalink "trouble.xml" } let model = DisplayCustomFeed.FromFeed [||] feed
let model = DisplayCustomFeed.FromFeed [||] feed Expect.equal model.Id "bad-feed" "Id not filled properly"
Expect.equal model.Id "bad-feed" "Id not filled properly" Expect.equal model.Source "Category: --INVALID; DELETE THIS FEED--" "Source not filled properly"
Expect.equal model.Source "Category: --INVALID; DELETE THIS FEED--" "Source not filled properly" Expect.equal model.Path "trouble.xml" "Path not filled properly"
Expect.equal model.Path "trouble.xml" "Path not filled properly" Expect.isFalse model.IsPodcast "IsPodcast not filled properly"
Expect.isFalse model.IsPodcast "IsPodcast not filled properly" }
} test "succeeds for a feed for a tag" {
test "succeeds for a feed for a tag" { let feed =
let feed = { Id = CustomFeedId "tag-feed"
{ Id = CustomFeedId "tag-feed" Source = Tag "testing"
Source = Tag "testing" Path = Permalink "testing-posts.xml"
Path = Permalink "testing-posts.xml" Podcast = Some PodcastOptions.Empty }
Podcast = Some PodcastOptions.Empty } let model = DisplayCustomFeed.FromFeed [||] feed
let model = DisplayCustomFeed.FromFeed [||] feed Expect.equal model.Id "tag-feed" "Id not filled properly"
Expect.equal model.Id "tag-feed" "Id not filled properly" Expect.equal model.Source "Tag: testing" "Source not filled properly"
Expect.equal model.Source "Tag: testing" "Source not filled properly" Expect.equal model.Path "testing-posts.xml" "Path not filled properly"
Expect.equal model.Path "testing-posts.xml" "Path not filled properly" Expect.isTrue model.IsPodcast "IsPodcast not filled properly"
Expect.isTrue model.IsPodcast "IsPodcast not filled properly" }
} ]
]
/// Unit tests for the DisplayPage type /// Unit tests for the DisplayPage type
let displayPageTests = let displayPageTests = testList "DisplayPage" [
testList "DisplayPage" [ let page =
let page = { Page.Empty with
{ Page.Empty with Id = PageId "my-page"
Id = PageId "my-page" AuthorId = WebLogUserId "jim"
AuthorId = WebLogUserId "jim" Title = "A Fine Example"
Title = "A Fine Example" Permalink = Permalink "about/a-fine-example.html"
Permalink = Permalink "about/a-fine-example.html" PublishedOn = Noda.epoch
PublishedOn = Noda.epoch UpdatedOn = Noda.epoch + Duration.FromHours 1
UpdatedOn = Noda.epoch + Duration.FromHours 1 Text = """<a href="/link.html">Click Me!</a>"""
Text = """<a href="/link.html">Click Me!</a>""" Metadata = [ { Name = "unit"; Value = "test" } ] }
Metadata = [ { Name = "unit"; Value = "test" } ] } testList "FromPageMinimal" [
testList "FromPageMinimal" [ test "succeeds when page is default page" {
test "succeeds when page is default page" { let webLog = { WebLog.Empty with TimeZone = "Etc/GMT-1"; DefaultPage = "my-page" }
let webLog = { WebLog.Empty with TimeZone = "Etc/GMT-1"; DefaultPage = "my-page" } let model = DisplayPage.FromPageMinimal webLog page
let model = DisplayPage.FromPageMinimal webLog page Expect.equal model.Id "my-page" "Id not filled properly"
Expect.equal model.Id "my-page" "Id not filled properly" Expect.equal model.AuthorId "jim" "AuthorId not filled properly"
Expect.equal model.AuthorId "jim" "AuthorId not filled properly" Expect.equal model.Title "A Fine Example" "Title not filled properly"
Expect.equal model.Title "A Fine Example" "Title not filled properly" Expect.equal model.Permalink "about/a-fine-example.html" "Permalink not filled properly"
Expect.equal model.Permalink "about/a-fine-example.html" "Permalink not filled properly" Expect.equal
Expect.equal model.PublishedOn
model.PublishedOn ((Noda.epoch + Duration.FromHours 1).ToDateTimeUtc())
((Noda.epoch + Duration.FromHours 1).ToDateTimeUtc()) "PublishedOn not filled properly"
"PublishedOn not filled properly" Expect.equal
Expect.equal model.UpdatedOn ((Noda.epoch + Duration.FromHours 2).ToDateTimeUtc()) "UpdatedOn not filled properly"
model.UpdatedOn Expect.isFalse model.IsInPageList "IsInPageList should not have been set"
((Noda.epoch + Duration.FromHours 2).ToDateTimeUtc()) Expect.isTrue model.IsDefault "IsDefault should have been set"
"UpdatedOn not filled properly" Expect.equal model.Text "" "Text should have been blank"
Expect.isFalse model.IsInPageList "IsInPageList should not have been set" Expect.isEmpty model.Metadata "Metadata should have been empty"
Expect.isTrue model.IsDefault "IsDefault should have been set" }
Expect.equal model.Text "" "Text should have been blank" test "succeeds when page is not the default page" {
Expect.isEmpty model.Metadata "Metadata should have been empty" let model = DisplayPage.FromPageMinimal { WebLog.Empty with DefaultPage = "posts" } page
} Expect.isFalse model.IsDefault "IsDefault should not have been set"
test "succeeds when page is not the default page" { }
let model = DisplayPage.FromPageMinimal { WebLog.Empty with DefaultPage = "posts" } page
Expect.isFalse model.IsDefault "IsDefault should not have been set"
}
]
testList "FromPage" [
test "succeeds when the web log is on the domain root" {
let webLog = { WebLog.Empty with TimeZone = "Etc/GMT-4"; UrlBase = "https://example.com" }
let model = DisplayPage.FromPage webLog page
Expect.equal model.Id "my-page" "Id not filled properly"
Expect.equal model.AuthorId "jim" "AuthorId not filled properly"
Expect.equal model.Title "A Fine Example" "Title not filled properly"
Expect.equal model.Permalink "about/a-fine-example.html" "Permalink not filled properly"
Expect.equal
model.PublishedOn
((Noda.epoch + Duration.FromHours 4).ToDateTimeUtc())
"PublishedOn not filled properly"
Expect.equal
model.UpdatedOn
((Noda.epoch + Duration.FromHours 5).ToDateTimeUtc())
"UpdatedOn not filled properly"
Expect.isFalse model.IsInPageList "IsInPageList should not have been set"
Expect.isFalse model.IsDefault "IsDefault should not have been set"
Expect.equal model.Text """<a href="/link.html">Click Me!</a>""" "Text not filled properly"
Expect.equal model.Metadata.Length 1 "Metadata not filled properly"
}
test "succeeds when the web log is not on the domain root" {
let model = DisplayPage.FromPage { WebLog.Empty with UrlBase = "https://example.com/a/b/c" } page
Expect.equal model.Text """<a href="/a/b/c/link.html">Click Me!</a>""" "Text not filled properly"
}
]
] ]
testList "FromPage" [
test "succeeds when the web log is on the domain root" {
let webLog = { WebLog.Empty with TimeZone = "Etc/GMT-4"; UrlBase = "https://example.com" }
let model = DisplayPage.FromPage webLog page
Expect.equal model.Id "my-page" "Id not filled properly"
Expect.equal model.AuthorId "jim" "AuthorId not filled properly"
Expect.equal model.Title "A Fine Example" "Title not filled properly"
Expect.equal model.Permalink "about/a-fine-example.html" "Permalink not filled properly"
Expect.equal
model.PublishedOn
((Noda.epoch + Duration.FromHours 4).ToDateTimeUtc())
"PublishedOn not filled properly"
Expect.equal
model.UpdatedOn
((Noda.epoch + Duration.FromHours 5).ToDateTimeUtc())
"UpdatedOn not filled properly"
Expect.isFalse model.IsInPageList "IsInPageList should not have been set"
Expect.isFalse model.IsDefault "IsDefault should not have been set"
Expect.equal model.Text """<a href="/link.html">Click Me!</a>""" "Text not filled properly"
Expect.equal model.Metadata.Length 1 "Metadata not filled properly"
}
test "succeeds when the web log is not on the domain root" {
let model = DisplayPage.FromPage { WebLog.Empty with UrlBase = "https://example.com/a/b/c" } page
Expect.equal model.Text """<a href="/a/b/c/link.html">Click Me!</a>""" "Text not filled properly"
}
]
]
/// Unit tests for the DisplayRevision type /// Unit tests for the DisplayRevision type
let displayRevisionTests = let displayRevisionTests = test "DisplayRevision.FromRevision succeeds" {
test "DisplayRevision.FromRevision succeeds" { let model =
let model = DisplayRevision.FromRevision
DisplayRevision.FromRevision { WebLog.Empty with TimeZone = "Etc/GMT+1" }
{ WebLog.Empty with TimeZone = "Etc/GMT+1" } { Text = Html "howdy"; AsOf = Noda.epoch }
{ Text = Html "howdy"; AsOf = Noda.epoch } Expect.equal model.AsOf (Noda.epoch.ToDateTimeUtc()) "AsOf not filled properly"
Expect.equal model.AsOf (Noda.epoch.ToDateTimeUtc()) "AsOf not filled properly" Expect.equal model.AsOfLocal ((Noda.epoch - Duration.FromHours 1).ToDateTimeUtc()) "AsOfLocal not filled properly"
Expect.equal Expect.equal model.Format "HTML" "Format not filled properly"
model.AsOfLocal ((Noda.epoch - Duration.FromHours 1).ToDateTimeUtc()) "AsOfLocal not filled properly" }
Expect.equal model.Format "HTML" "Format not filled properly"
}
open System.IO open System.IO
/// Unit tests for the DisplayTheme type /// Unit tests for the DisplayTheme type
let displayThemeTests = let displayThemeTests = testList "DisplayTheme.FromTheme" [
testList "DisplayTheme.FromTheme" [ let theme =
let theme = { Id = ThemeId "the-theme"
{ Id = ThemeId "the-theme" Name = "Test Theme"
Name = "Test Theme" Version = "v0.1.2"
Version = "v0.1.2" Templates = [ ThemeTemplate.Empty; ThemeTemplate.Empty ] }
Templates = [ ThemeTemplate.Empty; ThemeTemplate.Empty ] } test "succeeds when theme is in use and not on disk" {
test "succeeds when theme is in use and not on disk" { let model =
let model = DisplayTheme.FromTheme
DisplayTheme.FromTheme (fun it -> Expect.equal it (ThemeId "the-theme") "The theme ID not passed correctly"; true) theme
(fun it -> Expect.equal it (ThemeId "the-theme") "The theme ID not passed correctly"; true) theme Expect.equal model.Id "the-theme" "Id not filled properly"
Expect.equal model.Id "the-theme" "Id not filled properly" Expect.equal model.Name "Test Theme" "Name not filled properly"
Expect.equal model.Name "Test Theme" "Name not filled properly" Expect.equal model.Version "v0.1.2" "Version not filled properly"
Expect.equal model.Version "v0.1.2" "Version not filled properly" Expect.equal model.TemplateCount 2 "TemplateCount not filled properly"
Expect.equal model.TemplateCount 2 "TemplateCount not filled properly" Expect.isTrue model.IsInUse "IsInUse should have been set"
Expect.isTrue model.IsInUse "IsInUse should have been set" Expect.isFalse model.IsOnDisk "IsOnDisk should not have been set"
Expect.isFalse model.IsOnDisk "IsOnDisk should not have been set" }
} test "succeeds when the theme is not in use as is on disk" {
test "succeeds when the theme is not in use as is on disk" { let file = File.Create "another-theme.zip"
let file = File.Create "another-theme.zip" try
try let model = DisplayTheme.FromTheme (fun _ -> false) { theme with Id = ThemeId "another" }
let model = DisplayTheme.FromTheme (fun _ -> false) { theme with Id = ThemeId "another" } Expect.isFalse model.IsInUse "IsInUse should not have been set"
Expect.isFalse model.IsInUse "IsInUse should not have been set" Expect.isTrue model.IsOnDisk "IsOnDisk should have been set"
Expect.isTrue model.IsOnDisk "IsOnDisk should have been set" finally
finally file.Close()
file.Close() file.Dispose()
file.Dispose() File.Delete "another-theme.zip"
File.Delete "another-theme.zip" }
} ]
]
/// Unit tests for the DisplayUpload type /// Unit tests for the DisplayUpload type
let displayUploadTests = let displayUploadTests = test "DisplayUpload.FromUpload succeeds" {
test "DisplayUpload.FromUpload succeeds" { let upload =
let upload = { Upload.Empty with
{ Upload.Empty with Id = UploadId "test-up"
Id = UploadId "test-up" Path = Permalink "2022/04/my-pic.jpg"
Path = Permalink "2022/04/my-pic.jpg" UpdatedOn = Noda.epoch }
UpdatedOn = Noda.epoch } let model = DisplayUpload.FromUpload { WebLog.Empty with TimeZone = "Etc/GMT-1" } Database upload
let model = DisplayUpload.FromUpload { WebLog.Empty with TimeZone = "Etc/GMT-1" } Database upload Expect.equal model.Id "test-up" "Id not filled properly"
Expect.equal model.Id "test-up" "Id not filled properly" Expect.equal model.Name "my-pic.jpg" "Name not filled properly"
Expect.equal model.Name "my-pic.jpg" "Name not filled properly" Expect.equal model.Path "2022/04/" "Path not filled properly"
Expect.equal model.Path "2022/04/" "Path not filled properly" Expect.equal model.Source "Database" "Source not filled properly"
Expect.equal model.Source "Database" "Source not filled properly" Expect.isSome model.UpdatedOn "There should have been an UpdatedOn value"
Expect.isSome model.UpdatedOn "There should have been an UpdatedOn value" Expect.equal
Expect.equal model.UpdatedOn.Value ((Noda.epoch + Duration.FromHours 1).ToDateTimeUtc()) "UpdatedOn not filled properly"
model.UpdatedOn.Value ((Noda.epoch + Duration.FromHours 1).ToDateTimeUtc()) "UpdatedOn not filled properly" }
}
/// Unit tests for the DisplayUser type /// Unit tests for the DisplayUser type
let displayUserTests = let displayUserTests = testList "DisplayUser.FromUser" [
testList "DisplayUser.FromUser" [
let minimalUser = let minimalUser =
{ WebLogUser.Empty with { WebLogUser.Empty with
Id = WebLogUserId "test-user" Id = WebLogUserId "test-user"
@ -246,47 +236,234 @@ let displayUserTests =
] ]
/// Unit tests for the EditCategoryModel type /// Unit tests for the EditCategoryModel type
let editCategoryModelTests = let editCategoryModelTests = testList "EditCategoryModel" [
testList "EditCategoryModel" [ testList "FromCategory" [
testList "FromCategory" [ let minimalCat = { Category.Empty with Id = CategoryId "test-cat"; Name = "test"; Slug = "test-slug" }
let minimalCat = { Category.Empty with Id = CategoryId "test-cat"; Name = "test"; Slug = "test-slug" } test "succeeds with minimal information" {
test "succeeds with minimal information" { let model = EditCategoryModel.FromCategory minimalCat
let model = EditCategoryModel.FromCategory minimalCat Expect.equal model.CategoryId "test-cat" "CategoryId not filled properly"
Expect.equal model.CategoryId "test-cat" "CategoryId not filled properly" Expect.equal model.Name "test" "Name not filled properly"
Expect.equal model.Name "test" "Name not filled properly" Expect.equal model.Slug "test-slug" "Slug not filled properly"
Expect.equal model.Slug "test-slug" "Slug not filled properly" Expect.equal model.Description "" "Description not filled properly"
Expect.equal model.Description "" "Description not filled properly" Expect.equal model.ParentId "" "ParentId not filled properly"
Expect.equal model.ParentId "" "ParentId not filled properly" }
} test "succeeds with complete information" {
test "succeeds with complete information" { let model =
let model = EditCategoryModel.FromCategory
EditCategoryModel.FromCategory { minimalCat with Description = Some "Testing"; ParentId = Some (CategoryId "parent") }
{ minimalCat with Description = Some "Testing"; ParentId = Some (CategoryId "parent") } Expect.equal model.Description "Testing" "Description not filled properly"
Expect.equal model.Description "Testing" "Description not filled properly" Expect.equal model.ParentId "parent" "ParentId not filled properly"
Expect.equal model.ParentId "parent" "ParentId not filled properly" }
}
]
testList "IsNew" [
test "succeeds for a new category" {
let model = EditCategoryModel.FromCategory { Category.Empty with Id = CategoryId "new" }
Expect.isTrue model.IsNew "Category should have been considered new"
}
test "succeeds for a non-new category" {
let model = EditCategoryModel.FromCategory Category.Empty
Expect.isFalse model.IsNew "Category should not have been considered new"
}
]
] ]
testList "IsNew" [
test "succeeds for a new category" {
let model = EditCategoryModel.FromCategory { Category.Empty with Id = CategoryId "new" }
Expect.isTrue model.IsNew "Category should have been considered new"
}
test "succeeds for a non-new category" {
let model = EditCategoryModel.FromCategory Category.Empty
Expect.isFalse model.IsNew "Category should not have been considered new"
}
]
]
/// All tests for the Domain namespace /// Unit tests for the EditCustomFeedModel type
let all = let editCustomFeedModelTests = testList "EditCustomFeedModel" [
testList let minimalPodcast =
"ViewModels" { PodcastOptions.Empty with
[ addBaseToRelativeUrlsTests Title = "My Minimal Podcast"
displayCustomFeedTests Summary = "As little as possible"
displayPageTests DisplayedAuthor = "The Tester"
displayRevisionTests Email = "thetester@example.com"
displayThemeTests ImageUrl = Permalink "upload/my-image.png"
displayUploadTests AppleCategory = "News"
displayUserTests Explicit = Clean }
editCategoryModelTests ] // A GUID with all zeroes, ending in "a"
let aGuid =
let guidBytes = Guid.Empty.ToByteArray()
guidBytes[15] <- byte 10
Guid guidBytes
let fullPodcast =
{ minimalPodcast with
Subtitle = Some "A Podcast about Little"
ItemsInFeed = 17
AppleSubcategory = Some "Analysis"
DefaultMediaType = Some "video/mpeg4"
MediaBaseUrl = Some "a/b/c"
PodcastGuid = Some aGuid
FundingUrl = Some "https://pay.me"
FundingText = Some "Gimme Money!"
Medium = Some Newsletter }
testList "FromFeed" [
test "succeeds with no podcast" {
let model =
EditCustomFeedModel.FromFeed
{ Id = CustomFeedId "test-feed"
Source = Category (CategoryId "no-podcast")
Path = Permalink "no-podcast.xml"
Podcast = None }
Expect.equal model.Id "test-feed" "Id not filled properly"
Expect.equal model.SourceType "category" "SourceType not filled properly"
Expect.equal model.SourceValue "no-podcast" "SourceValue not filled properly"
Expect.equal model.Path "no-podcast.xml" "Path not filled properly"
Expect.isFalse model.IsPodcast "IsPodcast should not have been set"
Expect.equal model.Title "" "Title should be the default value"
Expect.equal model.Subtitle "" "Subtitle should be the default value"
Expect.equal model.ItemsInFeed 25 "ItemsInFeed should be the default value"
Expect.equal model.Summary "" "Summary should be the default value"
Expect.equal model.DisplayedAuthor "" "DisplayedAuthor should be the default value"
Expect.equal model.Email "" "Email should be the default value"
Expect.equal model.ImageUrl "" "ImageUrl should be the default value"
Expect.equal model.AppleCategory "" "AppleCategory should be the default value"
Expect.equal model.AppleSubcategory "" "AppleSubcategory should be the default value"
Expect.equal model.Explicit "no" "Explicit should be the default value"
Expect.equal model.DefaultMediaType "audio/mpeg" "DefaultMediaType should be the default value"
Expect.equal model.MediaBaseUrl "" "MediaBaseUrl should be the default value"
Expect.equal model.FundingUrl "" "FundingUrl should be the default value"
Expect.equal model.FundingText "" "FundingText should be the default value"
Expect.equal model.PodcastGuid "" "PodcastGuid should be the default value"
Expect.equal model.Medium "" "Medium should be the default value"
}
test "succeeds with minimal podcast" {
let model =
EditCustomFeedModel.FromFeed
{ Id = CustomFeedId "minimal-feed"
Source = Tag "min-podcast"
Path = Permalink "min-podcast.xml"
Podcast = Some minimalPodcast }
Expect.equal model.Id "minimal-feed" "Id not filled properly"
Expect.equal model.SourceType "tag" "SourceType not filled properly"
Expect.equal model.SourceValue "min-podcast" "SourceValue not filled properly"
Expect.equal model.Path "min-podcast.xml" "Path not filled properly"
Expect.isTrue model.IsPodcast "IsPodcast should have been set"
Expect.equal model.Title "My Minimal Podcast" "Title not filled properly"
Expect.equal model.Subtitle "" "Subtitle not filled properly (should be blank)"
Expect.equal model.ItemsInFeed 0 "ItemsInFeed not filled properly"
Expect.equal model.Summary "As little as possible" "Summary not filled properly"
Expect.equal model.DisplayedAuthor "The Tester" "DisplayedAuthor not filled properly"
Expect.equal model.Email "thetester@example.com" "Email not filled properly"
Expect.equal model.ImageUrl "upload/my-image.png" "ImageUrl not filled properly"
Expect.equal model.AppleCategory "News" "AppleCategory not filled properly"
Expect.equal model.AppleSubcategory "" "AppleSubcategory not filled properly (should be blank)"
Expect.equal model.Explicit "clean" "Explicit not filled properly"
Expect.equal model.DefaultMediaType "" "DefaultMediaType not filled properly (should be blank)"
Expect.equal model.MediaBaseUrl "" "MediaBaseUrl not filled properly (should be blank)"
Expect.equal model.FundingUrl "" "FundingUrl not filled properly (should be blank)"
Expect.equal model.FundingText "" "FundingText not filled properly (should be blank)"
Expect.equal model.PodcastGuid "" "PodcastGuid not filled properly (should be blank)"
Expect.equal model.Medium "" "Medium not filled properly (should be blank)"
}
test "succeeds with full podcast" {
let model =
EditCustomFeedModel.FromFeed
{ Id = CustomFeedId "full-feed"
Source = Tag "whole-enchilada"
Path = Permalink "full-podcast.xml"
Podcast = Some fullPodcast }
Expect.equal model.Id "full-feed" "Id not filled properly"
Expect.equal model.SourceType "tag" "SourceType not filled properly"
Expect.equal model.SourceValue "whole-enchilada" "SourceValue not filled properly"
Expect.equal model.Path "full-podcast.xml" "Path not filled properly"
Expect.isTrue model.IsPodcast "IsPodcast should have been set"
Expect.equal model.Title "My Minimal Podcast" "Title not filled properly"
Expect.equal model.Subtitle "A Podcast about Little" "Subtitle not filled properly"
Expect.equal model.ItemsInFeed 17 "ItemsInFeed not filled properly"
Expect.equal model.Summary "As little as possible" "Summary not filled properly"
Expect.equal model.DisplayedAuthor "The Tester" "DisplayedAuthor not filled properly"
Expect.equal model.Email "thetester@example.com" "Email not filled properly"
Expect.equal model.ImageUrl "upload/my-image.png" "ImageUrl not filled properly"
Expect.equal model.AppleCategory "News" "AppleCategory not filled properly"
Expect.equal model.AppleSubcategory "Analysis" "AppleSubcategory not filled properly"
Expect.equal model.Explicit "clean" "Explicit not filled properly"
Expect.equal model.DefaultMediaType "video/mpeg4" "DefaultMediaType not filled properly"
Expect.equal model.MediaBaseUrl "a/b/c" "MediaBaseUrl not filled properly"
Expect.equal model.FundingUrl "https://pay.me" "FundingUrl not filled properly"
Expect.equal model.FundingText "Gimme Money!" "FundingText not filled properly"
Expect.equal model.PodcastGuid "00000000-0000-0000-0000-00000000000a" "PodcastGuid not filled properly"
Expect.equal model.Medium "newsletter" "Medium not filled properly"
}
]
testList "UpdateFeed" [
test "succeeds with no podcast" {
let model =
{ EditCustomFeedModel.Empty with SourceType = "tag"; SourceValue = "no-audio"; Path = "no-podcast.xml" }
let feed =
model.UpdateFeed
{ CustomFeed.Empty with Id = CustomFeedId "no-podcast-feed"; Podcast = Some fullPodcast }
Expect.equal feed.Id (CustomFeedId "no-podcast-feed") "Id not filled properly"
Expect.equal feed.Source (Tag "no-audio") "Source not filled properly"
Expect.equal feed.Path (Permalink "no-podcast.xml") "Path not filled properly"
Expect.isNone feed.Podcast "Podcast not filled properly"
}
test "succeeds with minimal podcast" {
let model = EditCustomFeedModel.FromFeed { CustomFeed.Empty with Podcast = Some minimalPodcast }
let feed = model.UpdateFeed CustomFeed.Empty
Expect.equal feed.Source (Category (CategoryId "")) "Source not filled properly"
Expect.equal feed.Path (Permalink "") "Path not filled properly"
Expect.isSome feed.Podcast "Podcast should be present"
let podcast = feed.Podcast.Value
Expect.equal podcast.Title "My Minimal Podcast" "Podcast title not filled properly"
Expect.isNone podcast.Subtitle "Podcast subtitle not filled properly"
Expect.equal podcast.ItemsInFeed 0 "Podcast items in feed not filled properly"
Expect.equal podcast.Summary "As little as possible" "Podcast summary not filled properly"
Expect.equal podcast.DisplayedAuthor "The Tester" "Podcast author not filled properly"
Expect.equal podcast.Email "thetester@example.com" "Podcast email not filled properly"
Expect.equal podcast.Explicit Clean "Podcast explicit rating not filled properly"
Expect.equal podcast.AppleCategory "News" "Podcast Apple category not filled properly"
Expect.isNone podcast.AppleSubcategory "Podcast Apple subcategory not filled properly"
Expect.isNone podcast.DefaultMediaType "Podcast default media type not filled properly"
Expect.isNone podcast.MediaBaseUrl "Podcast media base URL not filled properly"
Expect.isNone podcast.PodcastGuid "Podcast GUID not filled properly"
Expect.isNone podcast.FundingUrl "Podcast funding URL not filled properly"
Expect.isNone podcast.FundingText "Podcast funding text not filled properly"
Expect.isNone podcast.Medium "Podcast medium not filled properly"
}
test "succeeds with full podcast" {
let model = EditCustomFeedModel.FromFeed { CustomFeed.Empty with Podcast = Some fullPodcast }
let feed = model.UpdateFeed CustomFeed.Empty
Expect.equal feed.Source (Category (CategoryId "")) "Source not filled properly"
Expect.equal feed.Path (Permalink "") "Path not filled properly"
Expect.isSome feed.Podcast "Podcast should be present"
let podcast = feed.Podcast.Value
Expect.equal podcast.Title "My Minimal Podcast" "Podcast title not filled properly"
Expect.equal podcast.Subtitle (Some "A Podcast about Little") "Podcast subtitle not filled properly"
Expect.equal podcast.ItemsInFeed 17 "Podcast items in feed not filled properly"
Expect.equal podcast.Summary "As little as possible" "Podcast summary not filled properly"
Expect.equal podcast.DisplayedAuthor "The Tester" "Podcast author not filled properly"
Expect.equal podcast.Email "thetester@example.com" "Podcast email not filled properly"
Expect.equal podcast.Explicit Clean "Podcast explicit rating not filled properly"
Expect.equal podcast.AppleCategory "News" "Podcast Apple category not filled properly"
Expect.equal podcast.AppleSubcategory (Some "Analysis") "Podcast Apple subcategory not filled properly"
Expect.equal podcast.DefaultMediaType (Some "video/mpeg4") "Podcast default media type not filled properly"
Expect.equal podcast.MediaBaseUrl (Some "a/b/c") "Podcast media base URL not filled properly"
Expect.equal podcast.PodcastGuid (Some aGuid) "Podcast GUID not filled properly"
Expect.equal podcast.FundingUrl (Some "https://pay.me") "Podcast funding URL not filled properly"
Expect.equal podcast.FundingText (Some "Gimme Money!") "Podcast funding text not filled properly"
Expect.equal podcast.Medium (Some Newsletter) "Podcast medium not filled properly"
}
]
]
/// Unit tests for the EditMyInfoModel type
let editMyInfoModelTests = test "EditMyInfoModel.FromUser succeeds" {
let model = EditMyInfoModel.FromUser { WebLogUser.Empty with FirstName = "A"; LastName = "B"; PreferredName = "C" }
Expect.equal model.FirstName "A" "FirstName not filled properly"
Expect.equal model.LastName "B" "LastName not filled properly"
Expect.equal model.PreferredName "C" "PreferredName not filled properly"
Expect.equal model.NewPassword "" "NewPassword not filled properly"
Expect.equal model.NewPasswordConfirm "" "NewPasswordConfirm not filled properly"
}
/// All tests in the Domain.ViewModels file
let all = testList "ViewModels" [
addBaseToRelativeUrlsTests
displayCustomFeedTests
displayPageTests
displayRevisionTests
displayThemeTests
displayUploadTests
displayUserTests
editCategoryModelTests
editCustomFeedModelTests
editMyInfoModelTests
]