Split tests into separate files
This commit is contained in:
parent
10affa2def
commit
29cbf486db
90
src/MyWebLog.Tests/DataTypesTests.fs
Normal file
90
src/MyWebLog.Tests/DataTypesTests.fs
Normal file
@ -0,0 +1,90 @@
|
||||
module DataTypesTests
|
||||
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
|
||||
/// Unit tests for the WebLog type
|
||||
let webLogTests =
|
||||
testList "WebLog" [
|
||||
testList "ExtraPath" [
|
||||
test "succeeds 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" {
|
||||
Expect.equal
|
||||
{ WebLog.Empty with UrlBase = "https://example.com" }.ExtraPath
|
||||
""
|
||||
"Extra path should have been blank for domain root"
|
||||
}
|
||||
test "succeeds for single subdirectory" {
|
||||
Expect.equal
|
||||
{ WebLog.Empty with UrlBase = "https://a.com/sub" }.ExtraPath
|
||||
"/sub"
|
||||
"Extra path incorrect for a single subdirectory"
|
||||
}
|
||||
test "succeeds for deeper nesting" {
|
||||
Expect.equal
|
||||
{ WebLog.Empty with UrlBase = "https://b.com/users/test/units" }.ExtraPath
|
||||
"/users/test/units"
|
||||
"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"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Unit tests for the WebLogUser type
|
||||
let webLogUserTests =
|
||||
testList "WebLogUser" [
|
||||
testList "DisplayName" [
|
||||
test "succeeds when a preferred name is present" {
|
||||
Expect.equal
|
||||
{ WebLogUser.Empty with
|
||||
FirstName = "Thomas"; PreferredName = "Tom"; LastName = "Tester" }.DisplayName
|
||||
"Tom Tester"
|
||||
"Display name incorrect when preferred name is present"
|
||||
}
|
||||
test "succeeds when a preferred name is absent" {
|
||||
Expect.equal
|
||||
{ WebLogUser.Empty with FirstName = "Test"; LastName = "Units" }.DisplayName
|
||||
"Test Units"
|
||||
"Display name incorrect when preferred name is absent"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// All tests for the Domain.DataTypes file
|
||||
let all =
|
||||
testList "DataTypes" [ webLogTests; webLogUserTests ]
|
@ -1,807 +0,0 @@
|
||||
module Domain
|
||||
|
||||
open System
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open NodaTime
|
||||
|
||||
// --- SUPPORT TYPES ---
|
||||
|
||||
/// Tests for the NodaTime-wrapping module
|
||||
let nodaTests =
|
||||
testList "Noda" [
|
||||
test "epoch succeeds" {
|
||||
Expect.equal
|
||||
(Noda.epoch.ToDateTimeUtc())
|
||||
(DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc))
|
||||
"The Unix epoch value is not correct"
|
||||
}
|
||||
test "toSecondsPrecision succeeds" {
|
||||
let testDate = Instant.FromDateTimeUtc(DateTime(1970, 1, 1, 0, 0, 0, 444, DateTimeKind.Utc))
|
||||
// testDate.
|
||||
Expect.equal
|
||||
((Noda.toSecondsPrecision testDate).ToDateTimeUtc())
|
||||
(Noda.epoch.ToDateTimeUtc())
|
||||
"Instant value was not rounded to seconds precision"
|
||||
}
|
||||
test "fromDateTime succeeds" {
|
||||
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"
|
||||
}
|
||||
]
|
||||
|
||||
/// Tests for the AccessLevel type
|
||||
let accessLevelTests =
|
||||
testList "AccessLevel" [
|
||||
testList "Parse" [
|
||||
test "succeeds for \"Author\"" {
|
||||
Expect.equal Author (AccessLevel.Parse "Author") "Author not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Editor\"" {
|
||||
Expect.equal Editor (AccessLevel.Parse "Editor") "Editor not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"WebLogAdmin\"" {
|
||||
Expect.equal WebLogAdmin (AccessLevel.Parse "WebLogAdmin") "WebLogAdmin not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Administrator\"" {
|
||||
Expect.equal Administrator (AccessLevel.Parse "Administrator") "Administrator not parsed correctly"
|
||||
}
|
||||
test "fails when given an unrecognized value" {
|
||||
Expect.throwsT<ArgumentException>
|
||||
(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"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the UploadDestination type
|
||||
let uploadDestinationTests =
|
||||
testList "UploadDestination" [
|
||||
testList "Parse" [
|
||||
test "succeeds for \"Database\"" {
|
||||
Expect.equal (UploadDestination.Parse "Database") Database "\"Database\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Disk\"" {
|
||||
Expect.equal (UploadDestination.Parse "Disk") Disk "\"Disk\" not parsed correctly"
|
||||
}
|
||||
test "fails for unrecognized value" {
|
||||
Expect.throwsT<ArgumentException>
|
||||
(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"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
// --- DATA TYPES ---
|
||||
|
||||
/// Unit tests for the WebLog type
|
||||
let webLogTests =
|
||||
testList "WebLog" [
|
||||
testList "ExtraPath" [
|
||||
test "succeeds 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" {
|
||||
Expect.equal
|
||||
{ WebLog.Empty with UrlBase = "https://example.com" }.ExtraPath
|
||||
""
|
||||
"Extra path should have been blank for domain root"
|
||||
}
|
||||
test "succeeds for single subdirectory" {
|
||||
Expect.equal
|
||||
{ WebLog.Empty with UrlBase = "https://a.com/sub" }.ExtraPath
|
||||
"/sub"
|
||||
"Extra path incorrect for a single subdirectory"
|
||||
}
|
||||
test "succeeds for deeper nesting" {
|
||||
Expect.equal
|
||||
{ WebLog.Empty with UrlBase = "https://b.com/users/test/units" }.ExtraPath
|
||||
"/users/test/units"
|
||||
"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"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Unit tests for the WebLogUser type
|
||||
let webLogUserTests =
|
||||
testList "WebLogUser" [
|
||||
testList "DisplayName" [
|
||||
test "succeeds when a preferred name is present" {
|
||||
Expect.equal
|
||||
{ WebLogUser.Empty with
|
||||
FirstName = "Thomas"; PreferredName = "Tom"; LastName = "Tester" }.DisplayName
|
||||
"Tom Tester"
|
||||
"Display name incorrect when preferred name is present"
|
||||
}
|
||||
test "succeeds when a preferred name is absent" {
|
||||
Expect.equal
|
||||
{ WebLogUser.Empty with FirstName = "Test"; LastName = "Units" }.DisplayName
|
||||
"Test Units"
|
||||
"Display name incorrect when preferred name is absent"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
// --- VIEW MODELS ---
|
||||
|
||||
open MyWebLog.ViewModels
|
||||
|
||||
/// Unit tests for the addBaseToRelativeUrls helper function
|
||||
let addBaseToRelativeUrlsTests =
|
||||
testList "PublicHelpers.addBaseToRelativeUrls" [
|
||||
test "succeeds when there is no extra URL path" {
|
||||
let testText = """<a href="/somewhere-else.html">Howdy></a>"""
|
||||
let modified = addBaseToRelativeUrls "" testText
|
||||
Expect.equal modified testText "The text should not have been modified"
|
||||
}
|
||||
test "succeeds with an extra URL path" {
|
||||
let testText =
|
||||
"""<a href="/my-link.htm"><img src="/pretty-picture.jpg"></a><a href="https://example.com>link</a>"""
|
||||
let expected =
|
||||
"""<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"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the DisplayCustomFeed type
|
||||
let displayCustomFeedTests =
|
||||
testList "DisplayCustomFeed.FromFeed" [
|
||||
test "succeeds for a feed for an existing category" {
|
||||
let cats =
|
||||
[| { DisplayCategory.Id = "abc"
|
||||
Slug = "a-b-c"
|
||||
Name = "My Lovely Category"
|
||||
Description = None
|
||||
ParentNames = [||]
|
||||
PostCount = 3 } |]
|
||||
let feed =
|
||||
{ CustomFeed.Empty with
|
||||
Id = CustomFeedId "test-feed"
|
||||
Source = Category (CategoryId "abc")
|
||||
Path = Permalink "test-feed.xml" }
|
||||
let model = DisplayCustomFeed.FromFeed cats feed
|
||||
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.Path "test-feed.xml" "Path not filled properly"
|
||||
Expect.isFalse model.IsPodcast "IsPodcast not filled properly"
|
||||
}
|
||||
test "succeeds for a feed for a non-existing category" {
|
||||
let feed =
|
||||
{ CustomFeed.Empty with
|
||||
Id = CustomFeedId "bad-feed"
|
||||
Source = Category (CategoryId "xyz")
|
||||
Path = Permalink "trouble.xml" }
|
||||
let model = DisplayCustomFeed.FromFeed [||] feed
|
||||
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.Path "trouble.xml" "Path not filled properly"
|
||||
Expect.isFalse model.IsPodcast "IsPodcast not filled properly"
|
||||
}
|
||||
test "succeeds for a feed for a tag" {
|
||||
let feed =
|
||||
{ Id = CustomFeedId "tag-feed"
|
||||
Source = Tag "testing"
|
||||
Path = Permalink "testing-posts.xml"
|
||||
Podcast = Some PodcastOptions.Empty }
|
||||
let model = DisplayCustomFeed.FromFeed [||] feed
|
||||
Expect.equal model.Id "tag-feed" "Id 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.isTrue model.IsPodcast "IsPodcast not filled properly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the DisplayPage type
|
||||
let displayPageTests =
|
||||
testList "DisplayPage" [
|
||||
let page =
|
||||
{ Page.Empty with
|
||||
Id = PageId "my-page"
|
||||
AuthorId = WebLogUserId "jim"
|
||||
Title = "A Fine Example"
|
||||
Permalink = Permalink "about/a-fine-example.html"
|
||||
PublishedOn = Noda.epoch
|
||||
UpdatedOn = Noda.epoch + Duration.FromHours 1
|
||||
Text = """<a href="/link.html">Click Me!</a>"""
|
||||
Metadata = [ { Name = "unit"; Value = "test" } ] }
|
||||
testList "FromPageMinimal" [
|
||||
test "succeeds when page is default page" {
|
||||
let webLog = { WebLog.Empty with TimeZone = "Etc/GMT-1"; DefaultPage = "my-page" }
|
||||
let model = DisplayPage.FromPageMinimal 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 1).ToDateTimeUtc())
|
||||
"PublishedOn not filled properly"
|
||||
Expect.equal
|
||||
model.UpdatedOn
|
||||
((Noda.epoch + Duration.FromHours 2).ToDateTimeUtc())
|
||||
"UpdatedOn not filled properly"
|
||||
Expect.isFalse model.IsInPageList "IsInPageList should not have been set"
|
||||
Expect.isTrue model.IsDefault "IsDefault should have been set"
|
||||
Expect.equal model.Text "" "Text should have been blank"
|
||||
Expect.isEmpty model.Metadata "Metadata should have been empty"
|
||||
}
|
||||
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"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Unit tests for the DisplayRevision type
|
||||
let displayRevisionTests =
|
||||
test "DisplayRevision.FromRevision succeeds" {
|
||||
let model =
|
||||
DisplayRevision.FromRevision
|
||||
{ WebLog.Empty with TimeZone = "Etc/GMT+1" }
|
||||
{ Text = Html "howdy"; AsOf = Noda.epoch }
|
||||
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 model.Format "HTML" "Format not filled properly"
|
||||
}
|
||||
|
||||
open System.IO
|
||||
|
||||
/// Unit tests for the DisplayTheme type
|
||||
let displayThemeTests =
|
||||
testList "DisplayTheme.FromTheme" [
|
||||
let theme =
|
||||
{ Id = ThemeId "the-theme"
|
||||
Name = "Test Theme"
|
||||
Version = "v0.1.2"
|
||||
Templates = [ ThemeTemplate.Empty; ThemeTemplate.Empty ] }
|
||||
test "succeeds when theme is in use and not on disk" {
|
||||
let model =
|
||||
DisplayTheme.FromTheme
|
||||
(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.Name "Test Theme" "Name not filled properly"
|
||||
Expect.equal model.Version "v0.1.2" "Version not filled properly"
|
||||
Expect.equal model.TemplateCount 2 "TemplateCount not filled properly"
|
||||
Expect.isTrue model.IsInUse "IsInUse should 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" {
|
||||
let file = File.Create "another-theme.zip"
|
||||
try
|
||||
let model = DisplayTheme.FromTheme (fun _ -> false) { theme with Id = ThemeId "another" }
|
||||
Expect.isFalse model.IsInUse "IsInUse should not have been set"
|
||||
Expect.isTrue model.IsOnDisk "IsOnDisk should have been set"
|
||||
finally
|
||||
file.Close()
|
||||
file.Dispose()
|
||||
File.Delete "another-theme.zip"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the DisplayUpload type
|
||||
let displayUploadTests =
|
||||
test "DisplayUpload.FromUpload succeeds" {
|
||||
let upload =
|
||||
{ Upload.Empty with
|
||||
Id = UploadId "test-up"
|
||||
Path = Permalink "2022/04/my-pic.jpg"
|
||||
UpdatedOn = Noda.epoch }
|
||||
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.Name "my-pic.jpg" "Name not filled properly"
|
||||
Expect.equal model.Path "2022/04/" "Path not filled properly"
|
||||
Expect.equal model.Source "Database" "Source not filled properly"
|
||||
Expect.isSome model.UpdatedOn "There should have been an UpdatedOn value"
|
||||
Expect.equal
|
||||
model.UpdatedOn.Value ((Noda.epoch + Duration.FromHours 1).ToDateTimeUtc()) "UpdatedOn not filled properly"
|
||||
}
|
||||
|
||||
/// Unit tests for the DisplayUser type
|
||||
let displayUserTests =
|
||||
testList "DisplayUser.FromUser" [
|
||||
let minimalUser =
|
||||
{ WebLogUser.Empty with
|
||||
Id = WebLogUserId "test-user"
|
||||
Email = "jim.james@example.com"
|
||||
FirstName = "Jim"
|
||||
LastName = "James"
|
||||
PreferredName = "John"
|
||||
AccessLevel = Editor
|
||||
CreatedOn = Noda.epoch }
|
||||
test "succeeds when the user has minimal information" {
|
||||
let model = DisplayUser.FromUser WebLog.Empty minimalUser
|
||||
Expect.equal model.Id "test-user" "Id not filled properly"
|
||||
Expect.equal model.Email "jim.james@example.com" "Email not filled properly"
|
||||
Expect.equal model.FirstName "Jim" "FirstName not filled properly"
|
||||
Expect.equal model.LastName "James" "LastName not filled properly"
|
||||
Expect.equal model.PreferredName "John" "PreferredName not filled properly"
|
||||
Expect.equal model.Url "" "Url not filled properly"
|
||||
Expect.equal model.AccessLevel "Editor" "AccessLevel not filled properly"
|
||||
Expect.equal model.CreatedOn (Noda.epoch.ToDateTimeUtc()) "CreatedOn not filled properly"
|
||||
Expect.isFalse model.LastSeenOn.HasValue "LastSeenOn should have been null"
|
||||
}
|
||||
test "succeeds when the user has all information" {
|
||||
let model =
|
||||
DisplayUser.FromUser
|
||||
{ WebLog.Empty with TimeZone = "Etc/GMT-1" }
|
||||
{ minimalUser with
|
||||
Url = Some "https://my.site"
|
||||
LastSeenOn = Some (Noda.epoch + Duration.FromDays 4) }
|
||||
Expect.equal model.Url "https://my.site" "Url not filled properly"
|
||||
Expect.equal
|
||||
model.CreatedOn ((Noda.epoch + Duration.FromHours 1).ToDateTimeUtc()) "CreatedOn not filled properly"
|
||||
Expect.isTrue model.LastSeenOn.HasValue "LastSeenOn should not have been null"
|
||||
Expect.equal
|
||||
model.LastSeenOn.Value
|
||||
((Noda.epoch + Duration.FromDays 4 + Duration.FromHours 1).ToDateTimeUtc())
|
||||
"LastSeenOn not filled properly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the EditCategoryModel type
|
||||
let editCategoryModelTests =
|
||||
testList "EditCategoryModel" [
|
||||
testList "FromCategory" [
|
||||
let minimalCat = { Category.Empty with Id = CategoryId "test-cat"; Name = "test"; Slug = "test-slug" }
|
||||
test "succeeds with minimal information" {
|
||||
let model = EditCategoryModel.FromCategory minimalCat
|
||||
Expect.equal model.CategoryId "test-cat" "CategoryId 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.Description "" "Description not filled properly"
|
||||
Expect.equal model.ParentId "" "ParentId not filled properly"
|
||||
}
|
||||
test "succeeds with complete information" {
|
||||
let model =
|
||||
EditCategoryModel.FromCategory
|
||||
{ minimalCat with Description = Some "Testing"; ParentId = Some (CategoryId "parent") }
|
||||
Expect.equal model.Description "Testing" "Description 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"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// All tests for the Domain namespace
|
||||
let all =
|
||||
testList
|
||||
"Domain"
|
||||
[ // support types
|
||||
nodaTests
|
||||
accessLevelTests
|
||||
commentStatusTests
|
||||
explicitRatingTests
|
||||
episodeTests
|
||||
markupTextTests
|
||||
podcastMediumTests
|
||||
postStatusTests
|
||||
customFeedSourceTests
|
||||
themeAssetIdTests
|
||||
uploadDestinationTests
|
||||
// data types
|
||||
webLogTests
|
||||
webLogUserTests
|
||||
// view models
|
||||
addBaseToRelativeUrlsTests
|
||||
displayCustomFeedTests
|
||||
displayPageTests
|
||||
displayRevisionTests
|
||||
displayThemeTests
|
||||
displayUploadTests
|
||||
displayUserTests
|
||||
editCategoryModelTests ]
|
@ -5,7 +5,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Domain.fs" />
|
||||
<Compile Include="SupportTypesTests.fs" />
|
||||
<Compile Include="DataTypesTests.fs" />
|
||||
<Compile Include="ViewModelsTests.fs" />
|
||||
<Compile Include="Program.fs" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
let allTests =
|
||||
testList
|
||||
"MyWebLog"
|
||||
[ Domain.all ]
|
||||
[ testList "Domain" [ SupportTypesTests.all; DataTypesTests.all; ViewModelsTests.all ] ]
|
||||
|
||||
[<EntryPoint>]
|
||||
let main args = runTestsWithCLIArgs [] args allTests
|
||||
|
432
src/MyWebLog.Tests/SupportTypesTests.fs
Normal file
432
src/MyWebLog.Tests/SupportTypesTests.fs
Normal file
@ -0,0 +1,432 @@
|
||||
module SupportTypesTests
|
||||
|
||||
open System
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open NodaTime
|
||||
|
||||
/// Tests for the NodaTime-wrapping module
|
||||
let nodaTests =
|
||||
testList "Noda" [
|
||||
test "epoch succeeds" {
|
||||
Expect.equal
|
||||
(Noda.epoch.ToDateTimeUtc())
|
||||
(DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc))
|
||||
"The Unix epoch value is not correct"
|
||||
}
|
||||
test "toSecondsPrecision succeeds" {
|
||||
let testDate = Instant.FromDateTimeUtc(DateTime(1970, 1, 1, 0, 0, 0, 444, DateTimeKind.Utc))
|
||||
// testDate.
|
||||
Expect.equal
|
||||
((Noda.toSecondsPrecision testDate).ToDateTimeUtc())
|
||||
(Noda.epoch.ToDateTimeUtc())
|
||||
"Instant value was not rounded to seconds precision"
|
||||
}
|
||||
test "fromDateTime succeeds" {
|
||||
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"
|
||||
}
|
||||
]
|
||||
|
||||
/// Tests for the AccessLevel type
|
||||
let accessLevelTests =
|
||||
testList "AccessLevel" [
|
||||
testList "Parse" [
|
||||
test "succeeds for \"Author\"" {
|
||||
Expect.equal Author (AccessLevel.Parse "Author") "Author not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Editor\"" {
|
||||
Expect.equal Editor (AccessLevel.Parse "Editor") "Editor not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"WebLogAdmin\"" {
|
||||
Expect.equal WebLogAdmin (AccessLevel.Parse "WebLogAdmin") "WebLogAdmin not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Administrator\"" {
|
||||
Expect.equal Administrator (AccessLevel.Parse "Administrator") "Administrator not parsed correctly"
|
||||
}
|
||||
test "fails when given an unrecognized value" {
|
||||
Expect.throwsT<ArgumentException>
|
||||
(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"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the UploadDestination type
|
||||
let uploadDestinationTests =
|
||||
testList "UploadDestination" [
|
||||
testList "Parse" [
|
||||
test "succeeds for \"Database\"" {
|
||||
Expect.equal (UploadDestination.Parse "Database") Database "\"Database\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Disk\"" {
|
||||
Expect.equal (UploadDestination.Parse "Disk") Disk "\"Disk\" not parsed correctly"
|
||||
}
|
||||
test "fails for unrecognized value" {
|
||||
Expect.throwsT<ArgumentException>
|
||||
(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"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// All tests for the Domain.SupportTypes file
|
||||
let all =
|
||||
testList
|
||||
"SupportTypes"
|
||||
[ nodaTests
|
||||
accessLevelTests
|
||||
commentStatusTests
|
||||
explicitRatingTests
|
||||
episodeTests
|
||||
markupTextTests
|
||||
podcastMediumTests
|
||||
postStatusTests
|
||||
customFeedSourceTests
|
||||
themeAssetIdTests
|
||||
uploadDestinationTests ]
|
292
src/MyWebLog.Tests/ViewModelsTests.fs
Normal file
292
src/MyWebLog.Tests/ViewModelsTests.fs
Normal file
@ -0,0 +1,292 @@
|
||||
module ViewModelsTests
|
||||
|
||||
open System
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open MyWebLog.ViewModels
|
||||
open NodaTime
|
||||
|
||||
/// Unit tests for the addBaseToRelativeUrls helper function
|
||||
let addBaseToRelativeUrlsTests =
|
||||
testList "PublicHelpers.addBaseToRelativeUrls" [
|
||||
test "succeeds when there is no extra URL path" {
|
||||
let testText = """<a href="/somewhere-else.html">Howdy></a>"""
|
||||
let modified = addBaseToRelativeUrls "" testText
|
||||
Expect.equal modified testText "The text should not have been modified"
|
||||
}
|
||||
test "succeeds with an extra URL path" {
|
||||
let testText =
|
||||
"""<a href="/my-link.htm"><img src="/pretty-picture.jpg"></a><a href="https://example.com>link</a>"""
|
||||
let expected =
|
||||
"""<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"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the DisplayCustomFeed type
|
||||
let displayCustomFeedTests =
|
||||
testList "DisplayCustomFeed.FromFeed" [
|
||||
test "succeeds for a feed for an existing category" {
|
||||
let cats =
|
||||
[| { DisplayCategory.Id = "abc"
|
||||
Slug = "a-b-c"
|
||||
Name = "My Lovely Category"
|
||||
Description = None
|
||||
ParentNames = [||]
|
||||
PostCount = 3 } |]
|
||||
let feed =
|
||||
{ CustomFeed.Empty with
|
||||
Id = CustomFeedId "test-feed"
|
||||
Source = Category (CategoryId "abc")
|
||||
Path = Permalink "test-feed.xml" }
|
||||
let model = DisplayCustomFeed.FromFeed cats feed
|
||||
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.Path "test-feed.xml" "Path not filled properly"
|
||||
Expect.isFalse model.IsPodcast "IsPodcast not filled properly"
|
||||
}
|
||||
test "succeeds for a feed for a non-existing category" {
|
||||
let feed =
|
||||
{ CustomFeed.Empty with
|
||||
Id = CustomFeedId "bad-feed"
|
||||
Source = Category (CategoryId "xyz")
|
||||
Path = Permalink "trouble.xml" }
|
||||
let model = DisplayCustomFeed.FromFeed [||] feed
|
||||
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.Path "trouble.xml" "Path not filled properly"
|
||||
Expect.isFalse model.IsPodcast "IsPodcast not filled properly"
|
||||
}
|
||||
test "succeeds for a feed for a tag" {
|
||||
let feed =
|
||||
{ Id = CustomFeedId "tag-feed"
|
||||
Source = Tag "testing"
|
||||
Path = Permalink "testing-posts.xml"
|
||||
Podcast = Some PodcastOptions.Empty }
|
||||
let model = DisplayCustomFeed.FromFeed [||] feed
|
||||
Expect.equal model.Id "tag-feed" "Id 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.isTrue model.IsPodcast "IsPodcast not filled properly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the DisplayPage type
|
||||
let displayPageTests =
|
||||
testList "DisplayPage" [
|
||||
let page =
|
||||
{ Page.Empty with
|
||||
Id = PageId "my-page"
|
||||
AuthorId = WebLogUserId "jim"
|
||||
Title = "A Fine Example"
|
||||
Permalink = Permalink "about/a-fine-example.html"
|
||||
PublishedOn = Noda.epoch
|
||||
UpdatedOn = Noda.epoch + Duration.FromHours 1
|
||||
Text = """<a href="/link.html">Click Me!</a>"""
|
||||
Metadata = [ { Name = "unit"; Value = "test" } ] }
|
||||
testList "FromPageMinimal" [
|
||||
test "succeeds when page is default page" {
|
||||
let webLog = { WebLog.Empty with TimeZone = "Etc/GMT-1"; DefaultPage = "my-page" }
|
||||
let model = DisplayPage.FromPageMinimal 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 1).ToDateTimeUtc())
|
||||
"PublishedOn not filled properly"
|
||||
Expect.equal
|
||||
model.UpdatedOn
|
||||
((Noda.epoch + Duration.FromHours 2).ToDateTimeUtc())
|
||||
"UpdatedOn not filled properly"
|
||||
Expect.isFalse model.IsInPageList "IsInPageList should not have been set"
|
||||
Expect.isTrue model.IsDefault "IsDefault should have been set"
|
||||
Expect.equal model.Text "" "Text should have been blank"
|
||||
Expect.isEmpty model.Metadata "Metadata should have been empty"
|
||||
}
|
||||
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"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Unit tests for the DisplayRevision type
|
||||
let displayRevisionTests =
|
||||
test "DisplayRevision.FromRevision succeeds" {
|
||||
let model =
|
||||
DisplayRevision.FromRevision
|
||||
{ WebLog.Empty with TimeZone = "Etc/GMT+1" }
|
||||
{ Text = Html "howdy"; AsOf = Noda.epoch }
|
||||
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 model.Format "HTML" "Format not filled properly"
|
||||
}
|
||||
|
||||
open System.IO
|
||||
|
||||
/// Unit tests for the DisplayTheme type
|
||||
let displayThemeTests =
|
||||
testList "DisplayTheme.FromTheme" [
|
||||
let theme =
|
||||
{ Id = ThemeId "the-theme"
|
||||
Name = "Test Theme"
|
||||
Version = "v0.1.2"
|
||||
Templates = [ ThemeTemplate.Empty; ThemeTemplate.Empty ] }
|
||||
test "succeeds when theme is in use and not on disk" {
|
||||
let model =
|
||||
DisplayTheme.FromTheme
|
||||
(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.Name "Test Theme" "Name not filled properly"
|
||||
Expect.equal model.Version "v0.1.2" "Version not filled properly"
|
||||
Expect.equal model.TemplateCount 2 "TemplateCount not filled properly"
|
||||
Expect.isTrue model.IsInUse "IsInUse should 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" {
|
||||
let file = File.Create "another-theme.zip"
|
||||
try
|
||||
let model = DisplayTheme.FromTheme (fun _ -> false) { theme with Id = ThemeId "another" }
|
||||
Expect.isFalse model.IsInUse "IsInUse should not have been set"
|
||||
Expect.isTrue model.IsOnDisk "IsOnDisk should have been set"
|
||||
finally
|
||||
file.Close()
|
||||
file.Dispose()
|
||||
File.Delete "another-theme.zip"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the DisplayUpload type
|
||||
let displayUploadTests =
|
||||
test "DisplayUpload.FromUpload succeeds" {
|
||||
let upload =
|
||||
{ Upload.Empty with
|
||||
Id = UploadId "test-up"
|
||||
Path = Permalink "2022/04/my-pic.jpg"
|
||||
UpdatedOn = Noda.epoch }
|
||||
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.Name "my-pic.jpg" "Name not filled properly"
|
||||
Expect.equal model.Path "2022/04/" "Path not filled properly"
|
||||
Expect.equal model.Source "Database" "Source not filled properly"
|
||||
Expect.isSome model.UpdatedOn "There should have been an UpdatedOn value"
|
||||
Expect.equal
|
||||
model.UpdatedOn.Value ((Noda.epoch + Duration.FromHours 1).ToDateTimeUtc()) "UpdatedOn not filled properly"
|
||||
}
|
||||
|
||||
/// Unit tests for the DisplayUser type
|
||||
let displayUserTests =
|
||||
testList "DisplayUser.FromUser" [
|
||||
let minimalUser =
|
||||
{ WebLogUser.Empty with
|
||||
Id = WebLogUserId "test-user"
|
||||
Email = "jim.james@example.com"
|
||||
FirstName = "Jim"
|
||||
LastName = "James"
|
||||
PreferredName = "John"
|
||||
AccessLevel = Editor
|
||||
CreatedOn = Noda.epoch }
|
||||
test "succeeds when the user has minimal information" {
|
||||
let model = DisplayUser.FromUser WebLog.Empty minimalUser
|
||||
Expect.equal model.Id "test-user" "Id not filled properly"
|
||||
Expect.equal model.Email "jim.james@example.com" "Email not filled properly"
|
||||
Expect.equal model.FirstName "Jim" "FirstName not filled properly"
|
||||
Expect.equal model.LastName "James" "LastName not filled properly"
|
||||
Expect.equal model.PreferredName "John" "PreferredName not filled properly"
|
||||
Expect.equal model.Url "" "Url not filled properly"
|
||||
Expect.equal model.AccessLevel "Editor" "AccessLevel not filled properly"
|
||||
Expect.equal model.CreatedOn (Noda.epoch.ToDateTimeUtc()) "CreatedOn not filled properly"
|
||||
Expect.isFalse model.LastSeenOn.HasValue "LastSeenOn should have been null"
|
||||
}
|
||||
test "succeeds when the user has all information" {
|
||||
let model =
|
||||
DisplayUser.FromUser
|
||||
{ WebLog.Empty with TimeZone = "Etc/GMT-1" }
|
||||
{ minimalUser with
|
||||
Url = Some "https://my.site"
|
||||
LastSeenOn = Some (Noda.epoch + Duration.FromDays 4) }
|
||||
Expect.equal model.Url "https://my.site" "Url not filled properly"
|
||||
Expect.equal
|
||||
model.CreatedOn ((Noda.epoch + Duration.FromHours 1).ToDateTimeUtc()) "CreatedOn not filled properly"
|
||||
Expect.isTrue model.LastSeenOn.HasValue "LastSeenOn should not have been null"
|
||||
Expect.equal
|
||||
model.LastSeenOn.Value
|
||||
((Noda.epoch + Duration.FromDays 4 + Duration.FromHours 1).ToDateTimeUtc())
|
||||
"LastSeenOn not filled properly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the EditCategoryModel type
|
||||
let editCategoryModelTests =
|
||||
testList "EditCategoryModel" [
|
||||
testList "FromCategory" [
|
||||
let minimalCat = { Category.Empty with Id = CategoryId "test-cat"; Name = "test"; Slug = "test-slug" }
|
||||
test "succeeds with minimal information" {
|
||||
let model = EditCategoryModel.FromCategory minimalCat
|
||||
Expect.equal model.CategoryId "test-cat" "CategoryId 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.Description "" "Description not filled properly"
|
||||
Expect.equal model.ParentId "" "ParentId not filled properly"
|
||||
}
|
||||
test "succeeds with complete information" {
|
||||
let model =
|
||||
EditCategoryModel.FromCategory
|
||||
{ minimalCat with Description = Some "Testing"; ParentId = Some (CategoryId "parent") }
|
||||
Expect.equal model.Description "Testing" "Description 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"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// All tests for the Domain namespace
|
||||
let all =
|
||||
testList
|
||||
"ViewModels"
|
||||
[ addBaseToRelativeUrlsTests
|
||||
displayCustomFeedTests
|
||||
displayPageTests
|
||||
displayRevisionTests
|
||||
displayThemeTests
|
||||
displayUploadTests
|
||||
displayUserTests
|
||||
editCategoryModelTests ]
|
Loading…
Reference in New Issue
Block a user