Version 2.1 (#41)
- Add full chapter support (#6) - Add built-in redirect functionality (#39) - Support building Docker containers for release (#38) - Support canonical domain configuration (#37) - Add unit tests for domain/models and integration tests for all three data stores - Convert SQLite storage to use JSON documents, similar to PostgreSQL - Convert admin templates to Giraffe View Engine (from Liquid) - Add .NET 8 support
This commit was merged in pull request #41.
This commit is contained in:
150
src/MyWebLog.Tests/Data/CategoryDataTests.fs
Normal file
150
src/MyWebLog.Tests/Data/CategoryDataTests.fs
Normal file
@@ -0,0 +1,150 @@
|
||||
/// <summary>
|
||||
/// Integration tests for <see cref="ICategoryData" /> implementations
|
||||
/// </summary>
|
||||
module CategoryDataTests
|
||||
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open MyWebLog.Data
|
||||
|
||||
/// The ID of the root web log
|
||||
let rootId = WebLogId "uSitJEuD3UyzWC9jgOHc8g"
|
||||
|
||||
/// The ID of the Favorites category
|
||||
let private favoritesId = CategoryId "S5JflPsJ9EG7gA2LD4m92A"
|
||||
|
||||
let ``Add succeeds`` (data: IData) = task {
|
||||
let category =
|
||||
{ Category.Empty with Id = CategoryId "added-cat"; WebLogId = WebLogId "test"; Name = "Added"; Slug = "added" }
|
||||
do! data.Category.Add category
|
||||
let! stored = data.Category.FindById (CategoryId "added-cat") (WebLogId "test")
|
||||
Expect.isSome stored "The category should have been added"
|
||||
}
|
||||
|
||||
let ``CountAll succeeds when categories exist`` (data: IData) = task {
|
||||
let! count = data.Category.CountAll rootId
|
||||
Expect.equal count 3 "There should have been 3 categories"
|
||||
}
|
||||
|
||||
let ``CountAll succeeds when categories do not exist`` (data: IData) = task {
|
||||
let! count = data.Category.CountAll WebLogId.Empty
|
||||
Expect.equal count 0 "There should have been no categories"
|
||||
}
|
||||
|
||||
let ``CountTopLevel succeeds when top-level categories exist`` (data: IData) = task {
|
||||
let! count = data.Category.CountTopLevel rootId
|
||||
Expect.equal count 2 "There should have been 2 top-level categories"
|
||||
}
|
||||
|
||||
let ``CountTopLevel succeeds when no top-level categories exist`` (data: IData) = task {
|
||||
let! count = data.Category.CountTopLevel WebLogId.Empty
|
||||
Expect.equal count 0 "There should have been no top-level categories"
|
||||
}
|
||||
|
||||
let ``FindAllForView succeeds`` (data: IData) = task {
|
||||
let! all = data.Category.FindAllForView rootId
|
||||
Expect.equal all.Length 3 "There should have been 3 categories returned"
|
||||
Expect.equal all[0].Name "Favorites" "The first category is incorrect"
|
||||
Expect.equal all[0].PostCount 1 "There should be one post in this category"
|
||||
Expect.equal all[1].Name "Spitball" "The second category is incorrect"
|
||||
Expect.equal all[1].PostCount 2 "There should be two posts in this category"
|
||||
Expect.equal all[2].Name "Moonshot" "The third category is incorrect"
|
||||
Expect.equal all[2].PostCount 1 "There should be one post in this category"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a category is found`` (data: IData) = task {
|
||||
let! cat = data.Category.FindById favoritesId rootId
|
||||
Expect.isSome cat "There should have been a category returned"
|
||||
Expect.equal cat.Value.Name "Favorites" "The category retrieved is incorrect"
|
||||
Expect.equal cat.Value.Slug "favorites" "The slug is incorrect"
|
||||
Expect.equal cat.Value.Description (Some "Favorite posts") "The description is incorrect"
|
||||
Expect.isNone cat.Value.ParentId "There should have been no parent ID"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a category is not found`` (data: IData) = task {
|
||||
let! cat = data.Category.FindById CategoryId.Empty rootId
|
||||
Expect.isNone cat "There should not have been a category returned"
|
||||
}
|
||||
|
||||
let ``FindByWebLog succeeds when categories exist`` (data: IData) = task {
|
||||
let! cats = data.Category.FindByWebLog rootId
|
||||
Expect.equal cats.Length 3 "There should be 3 categories"
|
||||
Expect.exists cats (fun it -> it.Name = "Favorites") "Favorites category not found"
|
||||
Expect.exists cats (fun it -> it.Name = "Spitball") "Spitball category not found"
|
||||
Expect.exists cats (fun it -> it.Name = "Moonshot") "Moonshot category not found"
|
||||
}
|
||||
|
||||
let ``FindByWebLog succeeds when no categories exist`` (data: IData) = task {
|
||||
let! cats = data.Category.FindByWebLog WebLogId.Empty
|
||||
Expect.isEmpty cats "There should have been no categories returned"
|
||||
}
|
||||
|
||||
let ``Update succeeds`` (data: IData) = task {
|
||||
match! data.Category.FindById favoritesId rootId with
|
||||
| Some cat ->
|
||||
do! data.Category.Update { cat with Name = "My Favorites"; Slug = "my-favorites"; Description = None }
|
||||
match! data.Category.FindById favoritesId rootId with
|
||||
| Some updated ->
|
||||
Expect.equal updated.Name "My Favorites" "Name not updated properly"
|
||||
Expect.equal updated.Slug "my-favorites" "Slug not updated properly"
|
||||
Expect.isNone updated.Description "Description should have been removed"
|
||||
| None -> Expect.isTrue false "The updated favorites category could not be retrieved"
|
||||
| None -> Expect.isTrue false "The favorites category could not be retrieved"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when the category is deleted (no posts)`` (data: IData) = task {
|
||||
let! result = data.Category.Delete (CategoryId "added-cat") (WebLogId "test")
|
||||
Expect.equal result CategoryDeleted "The category should have been deleted"
|
||||
let! cat = data.Category.FindById (CategoryId "added-cat") (WebLogId "test")
|
||||
Expect.isNone cat "The deleted category should not still exist"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when the category does not exist`` (data: IData) = task {
|
||||
let! result = data.Category.Delete CategoryId.Empty (WebLogId "none")
|
||||
Expect.equal result CategoryNotFound "The category should not have been found"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when reassigning parent category to None`` (data: IData) = task {
|
||||
let moonshotId = CategoryId "ScVpyu1e7UiP7bDdge3ZEw"
|
||||
let spitballId = CategoryId "jw6N69YtTEWVHAO33jHU-w"
|
||||
let! result = data.Category.Delete spitballId rootId
|
||||
Expect.equal result ReassignedChildCategories "Child categories should have been reassigned"
|
||||
match! data.Category.FindById moonshotId rootId with
|
||||
| Some cat -> Expect.isNone cat.ParentId "Parent ID should have been cleared"
|
||||
| None -> Expect.isTrue false "Unable to find former child category"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when reassigning parent category to Some`` (data: IData) = task {
|
||||
do! data.Category.Add { Category.Empty with Id = CategoryId "a"; WebLogId = WebLogId "test"; Name = "A" }
|
||||
do! data.Category.Add
|
||||
{ Category.Empty with
|
||||
Id = CategoryId "b"
|
||||
WebLogId = WebLogId "test"
|
||||
Name = "B"
|
||||
ParentId = Some (CategoryId "a") }
|
||||
do! data.Category.Add
|
||||
{ Category.Empty with
|
||||
Id = CategoryId "c"
|
||||
WebLogId = WebLogId "test"
|
||||
Name = "C"
|
||||
ParentId = Some (CategoryId "b") }
|
||||
let! result = data.Category.Delete (CategoryId "b") (WebLogId "test")
|
||||
Expect.equal result ReassignedChildCategories "Child categories should have been reassigned"
|
||||
match! data.Category.FindById (CategoryId "c") (WebLogId "test") with
|
||||
| Some cat -> Expect.equal cat.ParentId (Some (CategoryId "a")) "Parent category ID not reassigned properly"
|
||||
| None -> Expect.isTrue false "Expected former child category not found"
|
||||
}
|
||||
|
||||
let ``Delete succeeds and removes category from posts`` (data: IData) = task {
|
||||
let moonshotId = CategoryId "ScVpyu1e7UiP7bDdge3ZEw"
|
||||
let postId = PostId "RCsCU2puYEmkpzotoi8p4g"
|
||||
match! data.Post.FindById postId rootId with
|
||||
| Some post ->
|
||||
Expect.equal post.CategoryIds [ moonshotId ] "Post category IDs are not as expected"
|
||||
let! result = data.Category.Delete moonshotId rootId
|
||||
Expect.equal result CategoryDeleted "The category should have been deleted (no children)"
|
||||
match! data.Post.FindById postId rootId with
|
||||
| Some p -> Expect.isEmpty p.CategoryIds "Category ID was not removed"
|
||||
| None -> Expect.isTrue false "The expected updated post was not found"
|
||||
| None -> Expect.isTrue false "The expected test post was not found"
|
||||
}
|
||||
296
src/MyWebLog.Tests/Data/ConvertersTests.fs
Normal file
296
src/MyWebLog.Tests/Data/ConvertersTests.fs
Normal file
@@ -0,0 +1,296 @@
|
||||
module ConvertersTests
|
||||
|
||||
open Expecto
|
||||
open Microsoft.FSharpLu.Json
|
||||
open MyWebLog
|
||||
open MyWebLog.Converters.Json
|
||||
open Newtonsoft.Json
|
||||
|
||||
/// Unit tests for the CategoryIdConverter type
|
||||
let categoryIdConverterTests = testList "CategoryIdConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(CategoryIdConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(CategoryId "test-cat-id", opts)
|
||||
Expect.equal after "\"test-cat-id\"" "Category ID serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<CategoryId>("\"test-cat-id\"", opts)
|
||||
Expect.equal after (CategoryId "test-cat-id") "Category ID not serialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the CommentIdConverter type
|
||||
let commentIdConverterTests = testList "CommentIdConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(CommentIdConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(CommentId "test-id", opts)
|
||||
Expect.equal after "\"test-id\"" "Comment ID serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<CommentId>("\"my-test\"", opts)
|
||||
Expect.equal after (CommentId "my-test") "Comment ID deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the CommentStatusConverter type
|
||||
let commentStatusConverterTests = testList "CommentStatusConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(CommentStatusConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(Approved, opts)
|
||||
Expect.equal after "\"Approved\"" "Comment status serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<CommentStatus>("\"Spam\"", opts)
|
||||
Expect.equal after Spam "Comment status deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the CustomFeedIdConverter type
|
||||
let customFeedIdConverterTests = testList "CustomFeedIdConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(CustomFeedIdConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(CustomFeedId "my-feed", opts)
|
||||
Expect.equal after "\"my-feed\"" "Custom feed ID serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<CustomFeedId>("\"feed-me\"", opts)
|
||||
Expect.equal after (CustomFeedId "feed-me") "Custom feed ID deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the CustomFeedSourceConverter type
|
||||
let customFeedSourceConverterTests = testList "CustomFeedSourceConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(CustomFeedSourceConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(Category (CategoryId "abc-123"), opts)
|
||||
Expect.equal after "\"category:abc-123\"" "Custom feed source serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<CustomFeedSource>("\"tag:testing\"", opts)
|
||||
Expect.equal after (Tag "testing") "Custom feed source deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the ExplicitRating type
|
||||
let explicitRatingConverterTests = testList "ExplicitRatingConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(ExplicitRatingConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(Yes, opts)
|
||||
Expect.equal after "\"yes\"" "Explicit rating serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<ExplicitRating>("\"clean\"", opts)
|
||||
Expect.equal after Clean "Explicit rating deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the MarkupText type
|
||||
let markupTextConverterTests = testList "MarkupTextConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(MarkupTextConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(Html "<h4>test</h4>", opts)
|
||||
Expect.equal after "\"HTML: <h4>test</h4>\"" "Markup text serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<MarkupText>("\"Markdown: #### test\"", opts)
|
||||
Expect.equal after (Markdown "#### test") "Markup text deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the PermalinkConverter type
|
||||
let permalinkConverterTests = testList "PermalinkConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(PermalinkConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(Permalink "2022/test", opts)
|
||||
Expect.equal after "\"2022/test\"" "Permalink serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<Permalink>("\"2023/unit.html\"", opts)
|
||||
Expect.equal after (Permalink "2023/unit.html") "Permalink deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the PageIdConverter type
|
||||
let pageIdConverterTests = testList "PageIdConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(PageIdConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(PageId "test-page", opts)
|
||||
Expect.equal after "\"test-page\"" "Page ID serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<PageId>("\"page-test\"", opts)
|
||||
Expect.equal after (PageId "page-test") "Page ID deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the PodcastMedium type
|
||||
let podcastMediumConverterTests = testList "PodcastMediumConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(PodcastMediumConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(Audiobook, opts)
|
||||
Expect.equal after "\"audiobook\"" "Podcast medium serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<PodcastMedium>("\"newsletter\"", opts)
|
||||
Expect.equal after Newsletter "Podcast medium deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the PostIdConverter type
|
||||
let postIdConverterTests = testList "PostIdConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(PostIdConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(PostId "test-post", opts)
|
||||
Expect.equal after "\"test-post\"" "Post ID serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<PostId>("\"post-test\"", opts)
|
||||
Expect.equal after (PostId "post-test") "Post ID deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the TagMapIdConverter type
|
||||
let tagMapIdConverterTests = testList "TagMapIdConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(TagMapIdConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(TagMapId "test-map", opts)
|
||||
Expect.equal after "\"test-map\"" "Tag map ID serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<TagMapId>("\"map-test\"", opts)
|
||||
Expect.equal after (TagMapId "map-test") "Tag map ID deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the ThemeAssetIdConverter type
|
||||
let themeAssetIdConverterTests = testList "ThemeAssetIdConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(ThemeAssetIdConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(ThemeAssetId (ThemeId "test", "unit.jpg"), opts)
|
||||
Expect.equal after "\"test/unit.jpg\"" "Theme asset ID serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<ThemeAssetId>("\"theme/test.png\"", opts)
|
||||
Expect.equal after (ThemeAssetId (ThemeId "theme", "test.png")) "Theme asset ID deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the ThemeIdConverter type
|
||||
let themeIdConverterTests = testList "ThemeIdConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(ThemeIdConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(ThemeId "test-theme", opts)
|
||||
Expect.equal after "\"test-theme\"" "Theme ID serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<ThemeId>("\"theme-test\"", opts)
|
||||
Expect.equal after (ThemeId "theme-test") "Theme ID deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the UploadIdConverter type
|
||||
let uploadIdConverterTests = testList "UploadIdConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(UploadIdConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(UploadId "test-up", opts)
|
||||
Expect.equal after "\"test-up\"" "Upload ID serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<UploadId>("\"up-test\"", opts)
|
||||
Expect.equal after (UploadId "up-test") "Upload ID deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the WebLogIdConverter type
|
||||
let webLogIdConverterTests = testList "WebLogIdConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(WebLogIdConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(WebLogId "test-web", opts)
|
||||
Expect.equal after "\"test-web\"" "Web log ID serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<WebLogId>("\"web-test\"", opts)
|
||||
Expect.equal after (WebLogId "web-test") "Web log ID deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the WebLogUserIdConverter type
|
||||
let webLogUserIdConverterTests = testList "WebLogUserIdConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(WebLogUserIdConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(WebLogUserId "test-user", opts)
|
||||
Expect.equal after "\"test-user\"" "Web log user ID serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<WebLogUserId>("\"user-test\"", opts)
|
||||
Expect.equal after (WebLogUserId "user-test") "Web log user ID deserialized incorrectly"
|
||||
}
|
||||
]
|
||||
|
||||
open NodaTime.Serialization.JsonNet
|
||||
|
||||
/// Unit tests for the Json.configure function
|
||||
let configureTests = test "Json.configure succeeds" {
|
||||
let has typ (converter: JsonConverter) = converter.GetType() = typ
|
||||
let ser = configure (JsonSerializer.Create())
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<CategoryIdConverter>) "Category ID converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<CommentIdConverter>) "Comment ID converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<CommentStatusConverter>) "Comment status converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<CustomFeedIdConverter>) "Custom feed ID converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<CustomFeedSourceConverter>) "Custom feed source converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<ExplicitRatingConverter>) "Explicit rating converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<MarkupTextConverter>) "Markup text converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<PermalinkConverter>) "Permalink converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<PageIdConverter>) "Page ID converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<PodcastMediumConverter>) "Podcast medium converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<PostIdConverter>) "Post ID converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<TagMapIdConverter>) "Tag map ID converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<ThemeAssetIdConverter>) "Theme asset ID converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<ThemeIdConverter>) "Theme ID converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<UploadIdConverter>) "Upload ID converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<WebLogIdConverter>) "Web log ID converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<WebLogUserIdConverter>) "Web log user ID converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has typeof<CompactUnionJsonConverter>) "F# type converter not found"
|
||||
Expect.hasCountOf ser.Converters 1u (has (NodaConverters.InstantConverter.GetType())) "NodaTime converter not found"
|
||||
Expect.equal ser.NullValueHandling NullValueHandling.Ignore "Null handling set incorrectly"
|
||||
Expect.equal ser.MissingMemberHandling MissingMemberHandling.Ignore "Missing member handling set incorrectly"
|
||||
}
|
||||
|
||||
/// All tests for the Data.Converters file
|
||||
let all = testList "Converters" [
|
||||
categoryIdConverterTests
|
||||
commentIdConverterTests
|
||||
commentStatusConverterTests
|
||||
customFeedIdConverterTests
|
||||
customFeedSourceConverterTests
|
||||
explicitRatingConverterTests
|
||||
markupTextConverterTests
|
||||
permalinkConverterTests
|
||||
pageIdConverterTests
|
||||
podcastMediumConverterTests
|
||||
postIdConverterTests
|
||||
tagMapIdConverterTests
|
||||
themeAssetIdConverterTests
|
||||
themeIdConverterTests
|
||||
uploadIdConverterTests
|
||||
webLogIdConverterTests
|
||||
webLogUserIdConverterTests
|
||||
configureTests
|
||||
]
|
||||
267
src/MyWebLog.Tests/Data/PageDataTests.fs
Normal file
267
src/MyWebLog.Tests/Data/PageDataTests.fs
Normal file
@@ -0,0 +1,267 @@
|
||||
/// <summary>
|
||||
/// Integration tests for <see cref="IPageData" /> implementations
|
||||
/// </summary>
|
||||
module PageDataTests
|
||||
|
||||
open System
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open MyWebLog.Data
|
||||
open NodaTime
|
||||
|
||||
/// The ID of the root web log
|
||||
let private rootId = CategoryDataTests.rootId
|
||||
|
||||
/// The ID of the "A cool page" page
|
||||
let coolPageId = PageId "hgc_BLEZ50SoAWLuPNISvA"
|
||||
|
||||
/// The published and updated time of the "A cool page" page
|
||||
let private coolPagePublished = Instant.FromDateTimeOffset(DateTimeOffset.Parse "2024-01-20T22:14:28Z")
|
||||
|
||||
/// The ID of the "Yet Another Page" page
|
||||
let private otherPageId = PageId "KouRjvSmm0Wz6TMD8xf67A"
|
||||
|
||||
let ``Add succeeds`` (data: IData) = task {
|
||||
let page =
|
||||
{ Id = PageId "added-page"
|
||||
WebLogId = WebLogId "test"
|
||||
AuthorId = WebLogUserId "the-author"
|
||||
Title = "A New Page"
|
||||
Permalink = Permalink "2024/the-page.htm"
|
||||
PublishedOn = Noda.epoch + Duration.FromDays 3
|
||||
UpdatedOn = Noda.epoch + Duration.FromDays 3 + Duration.FromMinutes 2L
|
||||
IsInPageList = true
|
||||
Template = Some "new-page-template"
|
||||
Text = "<h1>A new page</h1>"
|
||||
Metadata = [ { Name = "Meta Item"; Value = "Meta Value" } ]
|
||||
PriorPermalinks = [ Permalink "2024/the-new-page.htm" ]
|
||||
Revisions = [ { AsOf = Noda.epoch + Duration.FromDays 3; Text = Html "<h1>A new page</h1>" } ] }
|
||||
do! data.Page.Add page
|
||||
let! stored = data.Page.FindFullById (PageId "added-page") (WebLogId "test")
|
||||
Expect.isSome stored "The page should have been added"
|
||||
let pg = stored.Value
|
||||
Expect.equal pg.Id page.Id "ID not saved properly"
|
||||
Expect.equal pg.WebLogId page.WebLogId "Web log ID not saved properly"
|
||||
Expect.equal pg.AuthorId page.AuthorId "Author ID not saved properly"
|
||||
Expect.equal pg.Title page.Title "Title not saved properly"
|
||||
Expect.equal pg.Permalink page.Permalink "Permalink not saved properly"
|
||||
Expect.equal pg.PublishedOn page.PublishedOn "Published On not saved properly"
|
||||
Expect.equal pg.UpdatedOn page.UpdatedOn "Updated On not saved properly"
|
||||
Expect.equal pg.IsInPageList page.IsInPageList "Is in page list flag not saved properly"
|
||||
Expect.equal pg.Template page.Template "Template not saved properly"
|
||||
Expect.equal pg.Text page.Text "Text not saved properly"
|
||||
Expect.equal pg.Metadata page.Metadata "Metadata not saved properly"
|
||||
Expect.equal pg.PriorPermalinks page.PriorPermalinks "Prior permalinks not saved properly"
|
||||
Expect.equal pg.Revisions page.Revisions "Revisions not saved properly"
|
||||
}
|
||||
|
||||
let ``All succeeds`` (data: IData) = task {
|
||||
let! pages = data.Page.All rootId
|
||||
Expect.hasLength pages 2 "There should have been 2 pages retrieved"
|
||||
pages |> List.iteri (fun idx pg ->
|
||||
Expect.equal pg.Text "" $"Page {idx} should have had no text"
|
||||
Expect.isEmpty pg.Metadata $"Page {idx} should have had no metadata"
|
||||
Expect.isEmpty pg.Revisions $"Page {idx} should have had no revisions"
|
||||
Expect.isEmpty pg.PriorPermalinks $"Page {idx} should have had no prior permalinks")
|
||||
let! others = data.Page.All (WebLogId "not-there")
|
||||
Expect.isEmpty others "There should not be pages retrieved"
|
||||
}
|
||||
|
||||
let ``CountAll succeeds`` (data: IData) = task {
|
||||
let! pages = data.Page.CountAll rootId
|
||||
Expect.equal pages 2 "There should have been 2 pages counted"
|
||||
}
|
||||
|
||||
let ``CountListed succeeds`` (data: IData) = task {
|
||||
let! pages = data.Page.CountListed rootId
|
||||
Expect.equal pages 1 "There should have been 1 page in the page list"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a page is found`` (data: IData) = task {
|
||||
let! page = data.Page.FindById coolPageId rootId
|
||||
Expect.isSome page "A page should have been returned"
|
||||
let pg = page.Value
|
||||
Expect.equal pg.Id coolPageId "The wrong page was retrieved"
|
||||
Expect.equal pg.WebLogId rootId "The page's web log did not match the called parameter"
|
||||
Expect.equal pg.AuthorId (WebLogUserId "5EM2rimH9kONpmd2zQkiVA") "Author ID is incorrect"
|
||||
Expect.equal pg.Title "Page Title" "Title is incorrect"
|
||||
Expect.equal pg.Permalink (Permalink "a-cool-page.html") "Permalink is incorrect"
|
||||
Expect.equal pg.PublishedOn coolPagePublished "Published On is incorrect"
|
||||
Expect.equal pg.UpdatedOn coolPagePublished "Updated On is incorrect"
|
||||
Expect.isFalse pg.IsInPageList "Is in page list flag should not have been set"
|
||||
Expect.equal pg.Text "<h1 id=\"a-cool-page\">A Cool Page</h1>\n<p>It really is cool!</p>\n" "Text is incorrect"
|
||||
Expect.equal
|
||||
pg.Metadata [ { Name = "Cool"; Value = "true" }; { Name = "Warm"; Value = "false" } ] "Metadata is incorrect"
|
||||
Expect.isEmpty pg.Revisions "Revisions should not have been retrieved"
|
||||
Expect.isEmpty pg.PriorPermalinks "Prior permalinks should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a page is not found (incorrect weblog)`` (data: IData) = task {
|
||||
let! page = data.Page.FindById coolPageId (WebLogId "wrong")
|
||||
Expect.isNone page "The page should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a page is not found (bad page ID)`` (data: IData) = task {
|
||||
let! page = data.Page.FindById (PageId "missing") rootId
|
||||
Expect.isNone page "The page should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindByPermalink succeeds when a page is found`` (data: IData) = task {
|
||||
let! page = data.Page.FindByPermalink (Permalink "a-cool-page.html") rootId
|
||||
Expect.isSome page "A page should have been returned"
|
||||
let pg = page.Value
|
||||
Expect.equal pg.Id coolPageId "The wrong page was retrieved"
|
||||
Expect.isEmpty pg.Revisions "Revisions should not have been retrieved"
|
||||
Expect.isEmpty pg.PriorPermalinks "Prior permalinks should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindByPermalink succeeds when a page is not found (incorrect weblog)`` (data: IData) = task {
|
||||
let! page = data.Page.FindByPermalink (Permalink "a-cool-page.html") (WebLogId "wrong")
|
||||
Expect.isNone page "The page should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindByPermalink succeeds when a page is not found (no such permalink)`` (data: IData) = task {
|
||||
let! page = data.Page.FindByPermalink (Permalink "1970/no-www-then.html") rootId
|
||||
Expect.isNone page "The page should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindCurrentPermalink succeeds when a page is found`` (data: IData) = task {
|
||||
let! link = data.Page.FindCurrentPermalink [ Permalink "a-cool-pg.html"; Permalink "a-cool-pg.html/" ] rootId
|
||||
Expect.isSome link "A permalink should have been returned"
|
||||
Expect.equal link (Some (Permalink "a-cool-page.html")) "The wrong permalink was retrieved"
|
||||
}
|
||||
|
||||
let ``FindCurrentPermalink succeeds when a page is not found`` (data: IData) = task {
|
||||
let! link = data.Page.FindCurrentPermalink [ Permalink "blah/"; Permalink "blah" ] rootId
|
||||
Expect.isNone link "A permalink should not have been returned"
|
||||
}
|
||||
|
||||
let ``FindFullById succeeds when a page is found`` (data: IData) = task {
|
||||
let! page = data.Page.FindFullById coolPageId rootId
|
||||
Expect.isSome page "A page should have been returned"
|
||||
let pg = page.Value
|
||||
Expect.equal pg.Id coolPageId "The wrong page was retrieved"
|
||||
Expect.equal pg.WebLogId rootId "The page's web log did not match the called parameter"
|
||||
Expect.equal
|
||||
pg.Revisions
|
||||
[ { AsOf = coolPagePublished; Text = Markdown "# A Cool Page\n\nIt really is cool!" } ]
|
||||
"Revisions are incorrect"
|
||||
Expect.equal pg.PriorPermalinks [ Permalink "a-cool-pg.html" ] "Prior permalinks are incorrect"
|
||||
}
|
||||
|
||||
let ``FindFullById succeeds when a page is not found`` (data: IData) = task {
|
||||
let! page = data.Page.FindFullById (PageId "not-there") rootId
|
||||
Expect.isNone page "A page should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindFullByWebLog succeeds when pages are found`` (data: IData) = task {
|
||||
let! pages = data.Page.FindFullByWebLog rootId
|
||||
Expect.hasLength pages 2 "There should have been 2 pages returned"
|
||||
pages |> List.iter (fun pg ->
|
||||
Expect.contains [ coolPageId; otherPageId ] pg.Id $"Page ID {pg.Id} unexpected"
|
||||
if pg.Id = coolPageId then
|
||||
Expect.isNonEmpty pg.Metadata "Metadata should have been retrieved"
|
||||
Expect.isNonEmpty pg.PriorPermalinks "Prior permalinks should have been retrieved"
|
||||
Expect.isNonEmpty pg.Revisions "Revisions should have been retrieved")
|
||||
}
|
||||
|
||||
let ``FindFullByWebLog succeeds when pages are not found`` (data: IData) = task {
|
||||
let! pages = data.Page.FindFullByWebLog (WebLogId "does-not-exist")
|
||||
Expect.isEmpty pages "No pages should have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindListed succeeds when pages are found`` (data: IData) = task {
|
||||
let! pages = data.Page.FindListed rootId
|
||||
Expect.hasLength pages 1 "There should have been 1 page returned"
|
||||
Expect.equal pages[0].Id otherPageId "An unexpected page was returned"
|
||||
Expect.equal pages[0].Text "" "Text should not have been returned"
|
||||
Expect.isEmpty pages[0].PriorPermalinks "Prior permalinks should not have been retrieved"
|
||||
Expect.isEmpty pages[0].Revisions "Revisions should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindListed succeeds when pages are not found`` (data: IData) = task {
|
||||
let! pages = data.Page.FindListed (WebLogId "none")
|
||||
Expect.isEmpty pages "No pages should have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindPageOfPages succeeds when pages are found`` (data: IData) = task {
|
||||
let! pages = data.Page.FindPageOfPages rootId 1
|
||||
Expect.hasLength pages 2 "There should have been 2 page returned"
|
||||
Expect.equal pages[0].Id coolPageId "Pages not sorted correctly"
|
||||
pages |> List.iteri (fun idx pg ->
|
||||
Expect.notEqual pg.Text "" $"Text for page {idx} should have been retrieved"
|
||||
Expect.isEmpty pg.Metadata $"Metadata for page {idx} should not have been retrieved"
|
||||
Expect.isEmpty pg.PriorPermalinks $"Prior permalinks for page {idx} should not have been retrieved"
|
||||
Expect.isEmpty pg.Revisions $"Revisions for page {idx} should not have been retrieved")
|
||||
}
|
||||
|
||||
let ``FindPageOfPages succeeds when pages are not found`` (data: IData) = task {
|
||||
let! pages = data.Page.FindPageOfPages rootId 2
|
||||
Expect.isEmpty pages "No pages should have been retrieved"
|
||||
}
|
||||
|
||||
let ``Update succeeds when the page exists`` (data: IData) = task {
|
||||
let! page = data.Page.FindFullById coolPageId rootId
|
||||
Expect.isSome page "A page should have been returned"
|
||||
do! data.Page.Update
|
||||
{ page.Value with
|
||||
Title = "This Is Neat"
|
||||
Permalink = Permalink "neat-page.html"
|
||||
UpdatedOn = page.Value.PublishedOn + Duration.FromHours 5
|
||||
IsInPageList = true
|
||||
Text = "<p>I have been updated"
|
||||
Metadata = [ List.head page.Value.Metadata ]
|
||||
PriorPermalinks = [ Permalink "a-cool-page.html" ]
|
||||
Revisions =
|
||||
{ AsOf = page.Value.PublishedOn + Duration.FromHours 5; Text = Html "<p>I have been updated" }
|
||||
:: page.Value.Revisions }
|
||||
let! updated = data.Page.FindFullById coolPageId rootId
|
||||
Expect.isSome updated "The updated page should have been returned"
|
||||
let pg = updated.Value
|
||||
Expect.equal pg.Title "This Is Neat" "Title is incorrect"
|
||||
Expect.equal pg.Permalink (Permalink "neat-page.html") "Permalink is incorrect"
|
||||
Expect.equal pg.PublishedOn coolPagePublished "Published On is incorrect"
|
||||
Expect.equal pg.UpdatedOn (coolPagePublished + Duration.FromHours 5) "Updated On is incorrect"
|
||||
Expect.isTrue pg.IsInPageList "Is in page list flag should have been set"
|
||||
Expect.equal pg.Text "<p>I have been updated" "Text is incorrect"
|
||||
Expect.equal pg.Metadata [ { Name = "Cool"; Value = "true" } ] "Metadata is incorrect"
|
||||
Expect.equal pg.PriorPermalinks [ Permalink "a-cool-page.html" ] "Prior permalinks are incorrect"
|
||||
Expect.equal
|
||||
pg.Revisions
|
||||
[ { AsOf = coolPagePublished + Duration.FromHours 5; Text = Html "<p>I have been updated" }
|
||||
{ AsOf = coolPagePublished; Text = Markdown "# A Cool Page\n\nIt really is cool!" } ]
|
||||
"Revisions are incorrect"
|
||||
}
|
||||
|
||||
let ``Update succeeds when the page does not exist`` (data: IData) = task {
|
||||
let pageId = PageId "missing-page"
|
||||
do! data.Page.Update { Page.Empty with Id = pageId; WebLogId = rootId }
|
||||
let! page = data.Page.FindById pageId rootId
|
||||
Expect.isNone page "A page should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``UpdatePriorPermalinks succeeds when the page exists`` (data: IData) = task {
|
||||
let links = [ Permalink "link-1.html"; Permalink "link-1.aspx"; Permalink "link-3.php" ]
|
||||
let! found = data.Page.UpdatePriorPermalinks otherPageId rootId links
|
||||
Expect.isTrue found "The permalinks should have been updated"
|
||||
let! page = data.Page.FindFullById otherPageId rootId
|
||||
Expect.isSome page "The page should have been found"
|
||||
Expect.equal page.Value.PriorPermalinks links "The prior permalinks were not correct"
|
||||
}
|
||||
|
||||
let ``UpdatePriorPermalinks succeeds when the page does not exist`` (data: IData) = task {
|
||||
let! found =
|
||||
data.Page.UpdatePriorPermalinks (PageId "no-page") WebLogId.Empty
|
||||
[ Permalink "link-1.html"; Permalink "link-1.aspx"; Permalink "link-3.php" ]
|
||||
Expect.isFalse found "The permalinks should not have been updated"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when a page is deleted`` (data: IData) = task {
|
||||
let! deleted = data.Page.Delete coolPageId rootId
|
||||
Expect.isTrue deleted "The page should have been deleted"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when a page is not deleted`` (data: IData) = task {
|
||||
let! deleted = data.Page.Delete coolPageId rootId // this was deleted above
|
||||
Expect.isFalse deleted "A page should not have been deleted"
|
||||
}
|
||||
431
src/MyWebLog.Tests/Data/PostDataTests.fs
Normal file
431
src/MyWebLog.Tests/Data/PostDataTests.fs
Normal file
@@ -0,0 +1,431 @@
|
||||
/// <summary>
|
||||
/// Integration tests for <see cref="IPostData" /> implementations
|
||||
/// </summary>
|
||||
module PostDataTests
|
||||
|
||||
open System
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open MyWebLog.Data
|
||||
open NodaTime
|
||||
|
||||
/// The ID of the root web log
|
||||
let private rootId = CategoryDataTests.rootId
|
||||
|
||||
/// The ID of podcast episode 1
|
||||
let private episode1 = PostId "osxMfWGlAkyugUbJ1-xD1g"
|
||||
|
||||
/// The published instant for episode 1
|
||||
let private episode1Published = Instant.FromDateTimeOffset(DateTimeOffset.Parse "2024-01-20T22:24:01Z")
|
||||
|
||||
/// The ID of podcast episode 2
|
||||
let episode2 = PostId "l4_Eh4aFO06SqqJjOymNzA"
|
||||
|
||||
/// The ID of "Something May Happen" post
|
||||
let private something = PostId "QweKbWQiOkqqrjEdgP9wwg"
|
||||
|
||||
/// The published instant for "Something May Happen" post
|
||||
let private somethingPublished = Instant.FromDateTimeOffset(DateTimeOffset.Parse "2024-01-20T22:32:59Z")
|
||||
|
||||
/// The ID of "An Incomplete Thought" post
|
||||
let private incomplete = PostId "VweKbWQiOkqqrjEdgP9wwg"
|
||||
|
||||
/// The ID of "Test Post 1" post
|
||||
let private testPost1 = PostId "RCsCU2puYEmkpzotoi8p4g"
|
||||
|
||||
/// The published instant for "Test Post 1" post
|
||||
let private testPost1Published = Instant.FromDateTimeOffset(DateTimeOffset.Parse "2024-01-20T22:17:29Z")
|
||||
|
||||
/// The category IDs for "Spitball" (parent) and "Moonshot"
|
||||
let private testCatIds = [ CategoryId "jw6N69YtTEWVHAO33jHU-w"; CategoryId "ScVpyu1e7UiP7bDdge3ZEw" ]
|
||||
|
||||
/// Ensure that a list of posts has text for each post
|
||||
let private ensureHasText (posts: Post list) =
|
||||
for post in posts do Expect.isNotEmpty post.Text $"Text should not be blank (post ID {post.Id})"
|
||||
|
||||
/// Ensure that a list of posts has no revisions or prior permalinks
|
||||
let private ensureEmpty posts =
|
||||
for post in posts do
|
||||
Expect.isEmpty post.Revisions $"There should have been no revisions (post ID {post.Id})"
|
||||
Expect.isEmpty post.PriorPermalinks $"There should have been no prior permalinks (post ID {post.Id})"
|
||||
|
||||
let ``Add succeeds`` (data: IData) = task {
|
||||
let post =
|
||||
{ Id = PostId "a-new-post"
|
||||
WebLogId = WebLogId "test"
|
||||
AuthorId = WebLogUserId "test-author"
|
||||
Status = Published
|
||||
Title = "A New Test Post"
|
||||
Permalink = Permalink "2020/test-post.html"
|
||||
PublishedOn = Some (Noda.epoch + Duration.FromMinutes 1L)
|
||||
UpdatedOn = Noda.epoch + Duration.FromMinutes 3L
|
||||
Template = Some "fancy"
|
||||
Text = "<p>Test text here"
|
||||
CategoryIds = [ CategoryId "a"; CategoryId "b" ]
|
||||
Tags = [ "x"; "y"; "zed" ]
|
||||
Episode = Some { Episode.Empty with Media = "test-ep.mp3" }
|
||||
Metadata = [ { Name = "Meta"; Value = "Data" } ]
|
||||
PriorPermalinks = [ Permalink "2020/test-post-a.html" ]
|
||||
Revisions = [ { AsOf = Noda.epoch + Duration.FromMinutes 1L; Text = Html "<p>Test text here" } ] }
|
||||
do! data.Post.Add post
|
||||
let! stored = data.Post.FindFullById post.Id post.WebLogId
|
||||
Expect.isSome stored "The added post should have been retrieved"
|
||||
let it = stored.Value
|
||||
Expect.equal it.Id post.Id "ID not saved properly"
|
||||
Expect.equal it.WebLogId post.WebLogId "Web log ID not saved properly"
|
||||
Expect.equal it.AuthorId post.AuthorId "Author ID not saved properly"
|
||||
Expect.equal it.Status post.Status "Status not saved properly"
|
||||
Expect.equal it.Title post.Title "Title not saved properly"
|
||||
Expect.equal it.Permalink post.Permalink "Permalink not saved properly"
|
||||
Expect.equal it.PublishedOn post.PublishedOn "Published On not saved properly"
|
||||
Expect.equal it.UpdatedOn post.UpdatedOn "Updated On not saved properly"
|
||||
Expect.equal it.Template post.Template "Template not saved properly"
|
||||
Expect.equal it.Text post.Text "Text not saved properly"
|
||||
Expect.equal it.CategoryIds post.CategoryIds "Category IDs not saved properly"
|
||||
Expect.equal it.Tags post.Tags "Tags not saved properly"
|
||||
Expect.equal it.Episode post.Episode "Episode not saved properly"
|
||||
Expect.equal it.Metadata post.Metadata "Metadata items not saved properly"
|
||||
Expect.equal it.PriorPermalinks post.PriorPermalinks "Prior permalinks not saved properly"
|
||||
Expect.equal it.Revisions post.Revisions "Revisions not saved properly"
|
||||
}
|
||||
|
||||
let ``CountByStatus succeeds`` (data: IData) = task {
|
||||
let! count = data.Post.CountByStatus Published rootId
|
||||
Expect.equal count 4 "There should be 4 published posts"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a post is found`` (data: IData) = task {
|
||||
let! post = data.Post.FindById episode1 rootId
|
||||
Expect.isSome post "There should have been a post returned"
|
||||
let it = post.Value
|
||||
Expect.equal it.Id episode1 "An incorrect post was retrieved"
|
||||
Expect.equal it.WebLogId rootId "The post belongs to an incorrect web log"
|
||||
Expect.equal it.AuthorId (WebLogUserId "5EM2rimH9kONpmd2zQkiVA") "Author ID is incorrect"
|
||||
Expect.equal it.Status Published "Status is incorrect"
|
||||
Expect.equal it.Title "Episode 1" "Title is incorrect"
|
||||
Expect.equal it.Permalink (Permalink "2024/episode-1.html") "Permalink is incorrect"
|
||||
Expect.equal it.PublishedOn (Some episode1Published) "Published On is incorrect"
|
||||
Expect.equal it.UpdatedOn episode1Published "Updated On is incorrect"
|
||||
Expect.equal it.Text "<p>It's the launch of my new podcast - y'all come listen!" "Text is incorrect"
|
||||
Expect.equal it.CategoryIds [ CategoryId "S5JflPsJ9EG7gA2LD4m92A" ] "Category IDs are incorrect"
|
||||
Expect.equal it.Tags [ "general"; "podcast" ] "Tags are incorrect"
|
||||
Expect.isSome it.Episode "There should be an episode associated with this post"
|
||||
let ep = it.Episode.Value
|
||||
Expect.equal ep.Media "episode-1.mp3" "Episode media is incorrect"
|
||||
Expect.equal ep.Length 124302L "Episode length is incorrect"
|
||||
Expect.equal
|
||||
ep.Duration (Some (Duration.FromMinutes 12L + Duration.FromSeconds 22L)) "Episode duration is incorrect"
|
||||
Expect.equal ep.ImageUrl (Some "images/ep1-cover.png") "Episode image URL is incorrect"
|
||||
Expect.equal ep.Subtitle (Some "An introduction to this podcast") "Episode subtitle is incorrect"
|
||||
Expect.equal ep.Explicit (Some Clean) "Episode explicit rating is incorrect"
|
||||
Expect.equal ep.ChapterFile (Some "uploads/chapters.json") "Episode chapter file is incorrect"
|
||||
Expect.equal ep.TranscriptUrl (Some "uploads/transcript.srt") "Episode transcript URL is incorrect"
|
||||
Expect.equal ep.TranscriptType (Some "application/srt") "Episode transcript type is incorrect"
|
||||
Expect.equal ep.TranscriptLang (Some "en") "Episode transcript language is incorrect"
|
||||
Expect.equal ep.TranscriptCaptions (Some true) "Episode transcript caption flag is incorrect"
|
||||
Expect.equal ep.SeasonNumber (Some 1) "Episode season number is incorrect"
|
||||
Expect.equal ep.SeasonDescription (Some "The First Season") "Episode season description is incorrect"
|
||||
Expect.equal ep.EpisodeNumber (Some 1.) "Episode number is incorrect"
|
||||
Expect.equal ep.EpisodeDescription (Some "The first episode ever!") "Episode description is incorrect"
|
||||
Expect.equal
|
||||
it.Metadata
|
||||
[ { Name = "Density"; Value = "Non-existent" }; { Name = "Intensity"; Value = "Low" } ]
|
||||
"Metadata is incorrect"
|
||||
ensureEmpty [ it ]
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a post is not found (incorrect weblog)`` (data: IData) = task {
|
||||
let! post = data.Post.FindById episode1 (WebLogId "wrong")
|
||||
Expect.isNone post "The post should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a post is not found (bad post ID)`` (data: IData) = task {
|
||||
let! post = data.Post.FindById (PostId "absent") rootId
|
||||
Expect.isNone post "The post should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindByPermalink succeeds when a post is found`` (data: IData) = task {
|
||||
let! post = data.Post.FindByPermalink (Permalink "2024/episode-1.html") rootId
|
||||
Expect.isSome post "A post should have been returned"
|
||||
let it = post.Value
|
||||
Expect.equal it.Id episode1 "The wrong post was retrieved"
|
||||
ensureEmpty [ it ]
|
||||
}
|
||||
|
||||
let ``FindByPermalink succeeds when a post is not found (incorrect weblog)`` (data: IData) = task {
|
||||
let! post = data.Post.FindByPermalink (Permalink "2024/episode-1.html") (WebLogId "incorrect")
|
||||
Expect.isNone post "The post should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindByPermalink succeeds when a post is not found (no such permalink)`` (data: IData) = task {
|
||||
let! post = data.Post.FindByPermalink (Permalink "404") rootId
|
||||
Expect.isNone post "The post should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindCurrentPermalink succeeds when a post is found`` (data: IData) = task {
|
||||
let! link = data.Post.FindCurrentPermalink [ Permalink "2024/ep-1.html"; Permalink "2024/ep-1.html/" ] rootId
|
||||
Expect.isSome link "A permalink should have been returned"
|
||||
Expect.equal link (Some (Permalink "2024/episode-1.html")) "The wrong permalink was retrieved"
|
||||
}
|
||||
|
||||
let ``FindCurrentPermalink succeeds when a post is not found`` (data: IData) = task {
|
||||
let! link = data.Post.FindCurrentPermalink [ Permalink "oops/"; Permalink "oops" ] rootId
|
||||
Expect.isNone link "A permalink should not have been returned"
|
||||
}
|
||||
|
||||
let ``FindFullById succeeds when a post is found`` (data: IData) = task {
|
||||
let! post = data.Post.FindFullById episode1 rootId
|
||||
Expect.isSome post "A post should have been returned"
|
||||
let it = post.Value
|
||||
Expect.equal it.Id episode1 "The wrong post was retrieved"
|
||||
Expect.equal it.WebLogId rootId "The post's web log did not match the called parameter"
|
||||
Expect.equal
|
||||
it.Revisions
|
||||
[ { AsOf = episode1Published; Text = Html "<p>It's the launch of my new podcast - y'all come listen!" } ]
|
||||
"Revisions are incorrect"
|
||||
Expect.equal it.PriorPermalinks [ Permalink "2024/ep-1.html" ] "Prior permalinks are incorrect"
|
||||
}
|
||||
|
||||
let ``FindFullById succeeds when a post is not found`` (data: IData) = task {
|
||||
let! post = data.Post.FindFullById (PostId "no-post") rootId
|
||||
Expect.isNone post "A page should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindFullByWebLog succeeds when posts are found`` (data: IData) = task {
|
||||
let! posts = data.Post.FindFullByWebLog rootId
|
||||
Expect.hasLength posts 5 "There should have been 5 posts returned"
|
||||
let allPosts = [ testPost1; episode1; episode2; something; incomplete ]
|
||||
posts |> List.iter (fun it ->
|
||||
Expect.contains allPosts it.Id $"Post ID {it.Id} unexpected"
|
||||
if it.Id = episode1 then
|
||||
Expect.isNonEmpty it.Metadata "Metadata should have been retrieved"
|
||||
Expect.isNonEmpty it.PriorPermalinks "Prior permalinks should have been retrieved"
|
||||
Expect.isNonEmpty it.Revisions "Revisions should have been retrieved")
|
||||
}
|
||||
|
||||
let ``FindFullByWebLog succeeds when posts are not found`` (data: IData) = task {
|
||||
let! posts = data.Post.FindFullByWebLog (WebLogId "nonexistent")
|
||||
Expect.isEmpty posts "No posts should have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindPageOfCategorizedPosts succeeds when posts are found`` (data: IData) = task {
|
||||
let! posts = data.Post.FindPageOfCategorizedPosts rootId testCatIds 1 1
|
||||
Expect.hasLength posts 2 "There should be 2 posts returned"
|
||||
Expect.equal posts[0].Id something "The wrong post was returned for page 1"
|
||||
ensureEmpty posts
|
||||
let! posts = data.Post.FindPageOfCategorizedPosts rootId testCatIds 2 1
|
||||
Expect.hasLength posts 1 "There should be 1 post returned"
|
||||
Expect.equal posts[0].Id testPost1 "The wrong post was returned for page 2"
|
||||
ensureEmpty posts
|
||||
}
|
||||
|
||||
let ``FindPageOfCategorizedPosts succeeds when finding a too-high page number`` (data: IData) = task {
|
||||
let! posts = data.Post.FindPageOfCategorizedPosts rootId testCatIds 17 2
|
||||
Expect.hasLength posts 0 "There should have been no posts returned (not enough posts)"
|
||||
}
|
||||
|
||||
let ``FindPageOfCategorizedPosts succeeds when a category has no posts`` (data: IData) = task {
|
||||
let! posts = data.Post.FindPageOfCategorizedPosts rootId [ CategoryId "nope" ] 1 1
|
||||
Expect.hasLength posts 0 "There should have been no posts returned (none match)"
|
||||
}
|
||||
|
||||
let ``FindPageOfPosts succeeds when posts are found`` (data: IData) = task {
|
||||
let ensureNoText (posts: Post list) =
|
||||
for post in posts do Expect.equal post.Text "" $"There should be no text (post ID {post.Id})"
|
||||
let! posts = data.Post.FindPageOfPosts rootId 1 2
|
||||
Expect.hasLength posts 3 "There should have been 3 posts returned for page 1"
|
||||
Expect.equal posts[0].Id incomplete "Page 1, post 1 is incorrect"
|
||||
Expect.equal posts[1].Id something "Page 1, post 2 is incorrect"
|
||||
Expect.equal posts[2].Id episode2 "Page 1, post 3 is incorrect"
|
||||
ensureNoText posts
|
||||
ensureEmpty posts
|
||||
let! posts = data.Post.FindPageOfPosts rootId 2 2
|
||||
Expect.hasLength posts 3 "There should have been 3 posts returned for page 2"
|
||||
Expect.equal posts[0].Id episode2 "Page 2, post 1 is incorrect"
|
||||
Expect.equal posts[1].Id episode1 "Page 2, post 2 is incorrect"
|
||||
Expect.equal posts[2].Id testPost1 "Page 2, post 3 is incorrect"
|
||||
ensureNoText posts
|
||||
ensureEmpty posts
|
||||
let! posts = data.Post.FindPageOfPosts rootId 3 2
|
||||
Expect.hasLength posts 1 "There should have been 1 post returned for page 3"
|
||||
Expect.equal posts[0].Id testPost1 "Page 3, post 1 is incorrect"
|
||||
ensureNoText posts
|
||||
ensureEmpty posts
|
||||
}
|
||||
|
||||
let ``FindPageOfPosts succeeds when finding a too-high page number`` (data: IData) = task {
|
||||
let! posts = data.Post.FindPageOfPosts rootId 88 3
|
||||
Expect.isEmpty posts "There should have been no posts returned (not enough posts)"
|
||||
}
|
||||
|
||||
let ``FindPageOfPosts succeeds when there are no posts`` (data: IData) = task {
|
||||
let! posts = data.Post.FindPageOfPosts (WebLogId "no-posts") 1 25
|
||||
Expect.isEmpty posts "There should have been no posts returned (no posts)"
|
||||
}
|
||||
|
||||
let ``FindPageOfPublishedPosts succeeds when posts are found`` (data: IData) = task {
|
||||
let! posts = data.Post.FindPageOfPublishedPosts rootId 1 3
|
||||
Expect.hasLength posts 4 "There should have been 4 posts returned for page 1"
|
||||
Expect.equal posts[0].Id something "Page 1, post 1 is incorrect"
|
||||
Expect.equal posts[1].Id episode2 "Page 1, post 2 is incorrect"
|
||||
Expect.equal posts[2].Id episode1 "Page 1, post 3 is incorrect"
|
||||
Expect.equal posts[3].Id testPost1 "Page 1, post 4 is incorrect"
|
||||
ensureHasText posts
|
||||
ensureEmpty posts
|
||||
let! posts = data.Post.FindPageOfPublishedPosts rootId 2 2
|
||||
Expect.hasLength posts 2 "There should have been 2 posts returned for page 2"
|
||||
Expect.equal posts[0].Id episode1 "Page 2, post 1 is incorrect"
|
||||
Expect.equal posts[1].Id testPost1 "Page 2, post 2 is incorrect"
|
||||
ensureHasText posts
|
||||
ensureEmpty posts
|
||||
}
|
||||
|
||||
let ``FindPageOfPublishedPosts succeeds when finding a too-high page number`` (data: IData) = task {
|
||||
let! posts = data.Post.FindPageOfPublishedPosts rootId 7 22
|
||||
Expect.isEmpty posts "There should have been no posts returned (not enough posts)"
|
||||
}
|
||||
|
||||
let ``FindPageOfPublishedPosts succeeds when there are no posts`` (data: IData) = task {
|
||||
let! posts = data.Post.FindPageOfPublishedPosts (WebLogId "empty") 1 8
|
||||
Expect.isEmpty posts "There should have been no posts returned (no posts)"
|
||||
}
|
||||
|
||||
let ``FindPageOfTaggedPosts succeeds when posts are found`` (data: IData) = task {
|
||||
let! posts = data.Post.FindPageOfTaggedPosts rootId "f#" 1 1
|
||||
Expect.hasLength posts 2 "There should have been 2 posts returned"
|
||||
Expect.equal posts[0].Id something "Page 1, post 1 is incorrect"
|
||||
Expect.equal posts[1].Id testPost1 "Page 1, post 2 is incorrect"
|
||||
ensureHasText posts
|
||||
ensureEmpty posts
|
||||
let! posts = data.Post.FindPageOfTaggedPosts rootId "f#" 2 1
|
||||
Expect.hasLength posts 1 "There should have been 1 posts returned"
|
||||
Expect.equal posts[0].Id testPost1 "Page 2, post 1 is incorrect"
|
||||
ensureHasText posts
|
||||
ensureEmpty posts
|
||||
}
|
||||
|
||||
let ``FindPageOfTaggedPosts succeeds when posts are found (excluding drafts)`` (data: IData) = task {
|
||||
let! posts = data.Post.FindPageOfTaggedPosts rootId "speculation" 1 10
|
||||
Expect.hasLength posts 1 "There should have been 1 post returned"
|
||||
Expect.equal posts[0].Id something "Post 1 is incorrect"
|
||||
ensureHasText posts
|
||||
ensureEmpty posts
|
||||
}
|
||||
|
||||
let ``FindPageOfTaggedPosts succeeds when finding a too-high page number`` (data: IData) = task {
|
||||
let! posts = data.Post.FindPageOfTaggedPosts rootId "f#" 436 18
|
||||
Expect.isEmpty posts "There should have been no posts returned (not enough posts)"
|
||||
}
|
||||
|
||||
let ``FindPageOfTaggedPosts succeeds when there are no posts`` (data: IData) = task {
|
||||
let! posts = data.Post.FindPageOfTaggedPosts rootId "non-existent-tag" 1 8
|
||||
Expect.isEmpty posts "There should have been no posts returned (no posts)"
|
||||
}
|
||||
|
||||
let ``FindSurroundingPosts succeeds when there is no next newer post`` (data: IData) = task {
|
||||
let! older, newer = data.Post.FindSurroundingPosts rootId somethingPublished
|
||||
Expect.isSome older "There should have been an older post"
|
||||
Expect.equal older.Value.Id episode2 "The next older post is incorrect"
|
||||
ensureHasText [ older.Value ]
|
||||
ensureEmpty [ older.Value ]
|
||||
Expect.isNone newer "There should not have been a newer post"
|
||||
}
|
||||
|
||||
let ``FindSurroundingPosts succeeds when there is no next older post`` (data: IData) = task {
|
||||
let! older, newer = data.Post.FindSurroundingPosts rootId testPost1Published
|
||||
Expect.isNone older "There should not have been an older post"
|
||||
Expect.isSome newer "There should have been a newer post"
|
||||
Expect.equal newer.Value.Id episode1 "The next newer post is incorrect"
|
||||
ensureHasText [ newer.Value ]
|
||||
ensureEmpty [ newer.Value ]
|
||||
}
|
||||
|
||||
let ``FindSurroundingPosts succeeds when older and newer exist`` (data: IData) = task {
|
||||
let! older, newer = data.Post.FindSurroundingPosts rootId episode1Published
|
||||
Expect.isSome older "There should have been an older post"
|
||||
Expect.equal older.Value.Id testPost1 "The next older post is incorrect"
|
||||
Expect.isSome newer "There should have been a newer post"
|
||||
Expect.equal newer.Value.Id episode2 "The next newer post is incorrect"
|
||||
ensureHasText [ older.Value; newer.Value ]
|
||||
ensureEmpty [ older.Value; newer.Value ]
|
||||
}
|
||||
|
||||
let ``Update succeeds when the post exists`` (data: IData) = task {
|
||||
let! before = data.Post.FindFullById (PostId "a-new-post") (WebLogId "test")
|
||||
Expect.isSome before "The post to be updated should have been found"
|
||||
do! data.Post.Update
|
||||
{ before.Value with
|
||||
AuthorId = WebLogUserId "someone-else"
|
||||
Status = Draft
|
||||
Title = "An Updated Test Post"
|
||||
Permalink = Permalink "2021/updated-post.html"
|
||||
PublishedOn = None
|
||||
UpdatedOn = Noda.epoch + Duration.FromDays 4
|
||||
Template = Some "other"
|
||||
Text = "<p>Updated text here"
|
||||
CategoryIds = [ CategoryId "c"; CategoryId "d"; CategoryId "e" ]
|
||||
Tags = [ "alpha"; "beta"; "nu"; "zeta" ]
|
||||
Episode = None
|
||||
Metadata = [ { Name = "Howdy"; Value = "Pardner" } ]
|
||||
PriorPermalinks = Permalink "2020/test-post.html" :: before.Value.PriorPermalinks
|
||||
Revisions =
|
||||
{ AsOf = Noda.epoch + Duration.FromDays 4; Text = Html "<p>Updated text here" }
|
||||
:: before.Value.Revisions }
|
||||
let! after = data.Post.FindFullById (PostId "a-new-post") (WebLogId "test")
|
||||
Expect.isSome after "The updated post should have been found"
|
||||
let post = after.Value
|
||||
Expect.equal post.AuthorId (WebLogUserId "someone-else") "Updated author is incorrect"
|
||||
Expect.equal post.Status Draft "Updated status is incorrect"
|
||||
Expect.equal post.Title "An Updated Test Post" "Updated title is incorrect"
|
||||
Expect.equal post.Permalink (Permalink "2021/updated-post.html") "Updated permalink is incorrect"
|
||||
Expect.isNone post.PublishedOn "Updated post should not have had a published-on date/time"
|
||||
Expect.equal post.UpdatedOn (Noda.epoch + Duration.FromDays 4) "Updated updated-on date/time is incorrect"
|
||||
Expect.equal post.Template (Some "other") "Updated template is incorrect"
|
||||
Expect.equal post.Text "<p>Updated text here" "Updated text is incorrect"
|
||||
Expect.equal
|
||||
post.CategoryIds [ CategoryId "c"; CategoryId "d"; CategoryId "e" ] "Updated category IDs are incorrect"
|
||||
Expect.equal post.Tags [ "alpha"; "beta"; "nu"; "zeta" ] "Updated tags are incorrect"
|
||||
Expect.isNone post.Episode "Update episode is incorrect"
|
||||
Expect.equal post.Metadata [ { Name = "Howdy"; Value = "Pardner" } ] "Updated metadata is incorrect"
|
||||
Expect.equal
|
||||
post.PriorPermalinks
|
||||
[ Permalink "2020/test-post.html"; Permalink "2020/test-post-a.html" ]
|
||||
"Updated prior permalinks are incorrect"
|
||||
Expect.equal
|
||||
post.Revisions
|
||||
[ { AsOf = Noda.epoch + Duration.FromDays 4; Text = Html "<p>Updated text here" }
|
||||
{ AsOf = Noda.epoch + Duration.FromMinutes 1L; Text = Html "<p>Test text here" } ]
|
||||
"Updated revisions are incorrect"
|
||||
}
|
||||
|
||||
let ``Update succeeds when the post does not exist`` (data: IData) = task {
|
||||
let postId = PostId "lost-post"
|
||||
do! data.Post.Update { Post.Empty with Id = postId; WebLogId = rootId }
|
||||
let! post = data.Post.FindById postId rootId
|
||||
Expect.isNone post "A post should not have been retrieved"
|
||||
}
|
||||
|
||||
let ``UpdatePriorPermalinks succeeds when the post exists`` (data: IData) = task {
|
||||
let links = [ Permalink "2024/ep-1.html"; Permalink "2023/ep-1.html" ]
|
||||
let! found = data.Post.UpdatePriorPermalinks episode1 rootId links
|
||||
Expect.isTrue found "The permalinks should have been updated"
|
||||
let! post = data.Post.FindFullById episode1 rootId
|
||||
Expect.isSome post "The post should have been found"
|
||||
Expect.equal post.Value.PriorPermalinks links "The prior permalinks were not correct"
|
||||
}
|
||||
|
||||
let ``UpdatePriorPermalinks succeeds when the post does not exist`` (data: IData) = task {
|
||||
let! found =
|
||||
data.Post.UpdatePriorPermalinks (PostId "silence") WebLogId.Empty [ Permalink "a.html"; Permalink "b.html" ]
|
||||
Expect.isFalse found "The permalinks should not have been updated"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when a post is deleted`` (data: IData) = task {
|
||||
let! deleted = data.Post.Delete episode2 rootId
|
||||
Expect.isTrue deleted "The post should have been deleted"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when a post is not deleted`` (data: IData) = task {
|
||||
let! deleted = data.Post.Delete episode2 rootId // this was deleted above
|
||||
Expect.isFalse deleted "A post should not have been deleted"
|
||||
}
|
||||
722
src/MyWebLog.Tests/Data/PostgresDataTests.fs
Normal file
722
src/MyWebLog.Tests/Data/PostgresDataTests.fs
Normal file
@@ -0,0 +1,722 @@
|
||||
module PostgresDataTests
|
||||
|
||||
open BitBadger.Documents.Postgres
|
||||
open Expecto
|
||||
open Microsoft.Extensions.Logging.Abstractions
|
||||
open MyWebLog
|
||||
open MyWebLog.Converters
|
||||
open MyWebLog.Data
|
||||
open Newtonsoft.Json
|
||||
open Npgsql
|
||||
open ThrowawayDb.Postgres
|
||||
|
||||
/// JSON serializer
|
||||
let private ser = Json.configure (JsonSerializer.CreateDefault())
|
||||
|
||||
/// The throwaway database (deleted when disposed)
|
||||
let mutable private db: ThrowawayDatabase option = None
|
||||
|
||||
/// Create a PostgresData instance for testing
|
||||
let private mkData () =
|
||||
PostgresData(NullLogger<PostgresData>(), ser) :> IData
|
||||
|
||||
/// The host for the PostgreSQL test database (defaults to localhost)
|
||||
let private testHost =
|
||||
RethinkDbDataTests.env "PG_HOST" "localhost"
|
||||
|
||||
/// The database name for the PostgreSQL test database (defaults to postgres)
|
||||
let private testDb =
|
||||
RethinkDbDataTests.env "PG_DB" "postgres"
|
||||
|
||||
/// The user ID for the PostgreSQL test database (defaults to postgres)
|
||||
let private testUser =
|
||||
RethinkDbDataTests.env "PG_USER" "postgres"
|
||||
|
||||
/// The password for the PostgreSQL test database (defaults to postgres)
|
||||
let private testPw =
|
||||
RethinkDbDataTests.env "PG_PW" "postgres"
|
||||
|
||||
/// Create a fresh environment from the root backup
|
||||
let private freshEnvironment () = task {
|
||||
if Option.isSome db then db.Value.Dispose()
|
||||
db <- Some (ThrowawayDatabase.Create $"Host={testHost};Database={testDb};User ID={testUser};Password={testPw}")
|
||||
let source = NpgsqlDataSourceBuilder db.Value.ConnectionString
|
||||
let _ = source.UseNodaTime()
|
||||
Configuration.useDataSource (source.Build())
|
||||
let env = mkData ()
|
||||
do! env.StartUp()
|
||||
// This exercises Restore for all implementations; all tests are dependent on it working as expected
|
||||
do! Maintenance.Backup.restoreBackup "root-weblog.json" None false false env
|
||||
}
|
||||
|
||||
/// Set up the environment for the PostgreSQL tests
|
||||
let private environmentSetUp = testTask "creating database" {
|
||||
do! freshEnvironment ()
|
||||
}
|
||||
|
||||
/// Integration tests for the Category implementation in PostgreSQL
|
||||
let private categoryTests = testList "Category" [
|
||||
testTask "Add succeeds" {
|
||||
do! CategoryDataTests.``Add succeeds`` (mkData ())
|
||||
}
|
||||
testList "CountAll" [
|
||||
testTask "succeeds when categories exist" {
|
||||
do! CategoryDataTests.``CountAll succeeds when categories exist`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when categories do not exist" {
|
||||
do! CategoryDataTests.``CountAll succeeds when categories do not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "CountTopLevel" [
|
||||
testTask "succeeds when top-level categories exist" {
|
||||
do! CategoryDataTests.``CountTopLevel succeeds when top-level categories exist`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when no top-level categories exist" {
|
||||
do! CategoryDataTests.``CountTopLevel succeeds when no top-level categories exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testTask "FindAllForView succeeds" {
|
||||
do! CategoryDataTests.``FindAllForView succeeds`` (mkData ())
|
||||
}
|
||||
testList "FindById" [
|
||||
testTask "succeeds when a category is found" {
|
||||
do! CategoryDataTests.``FindById succeeds when a category is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a category is not found" {
|
||||
do! CategoryDataTests.``FindById succeeds when a category is not found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindByWebLog" [
|
||||
testTask "succeeds when categories exist" {
|
||||
do! CategoryDataTests.``FindByWebLog succeeds when categories exist`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when no categories exist" {
|
||||
do! CategoryDataTests.``FindByWebLog succeeds when no categories exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testTask "Update succeeds" {
|
||||
do! CategoryDataTests.``Update succeeds`` (mkData ())
|
||||
}
|
||||
testList "Delete" [
|
||||
testTask "succeeds when the category is deleted (no posts)" {
|
||||
do! CategoryDataTests.``Delete succeeds when the category is deleted (no posts)`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the category does not exist" {
|
||||
do! CategoryDataTests.``Delete succeeds when the category does not exist`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when reassigning parent category to None" {
|
||||
do! CategoryDataTests.``Delete succeeds when reassigning parent category to None`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when reassigning parent category to Some" {
|
||||
do! CategoryDataTests.``Delete succeeds when reassigning parent category to Some`` (mkData ())
|
||||
}
|
||||
testTask "succeeds and removes category from posts" {
|
||||
do! CategoryDataTests.``Delete succeeds and removes category from posts`` (mkData ())
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Integration tests for the Page implementation in PostgreSQL
|
||||
let private pageTests = testList "Page" [
|
||||
testTask "Add succeeds" {
|
||||
do! PageDataTests.``Add succeeds`` (mkData ())
|
||||
}
|
||||
testTask "All succeeds" {
|
||||
do! PageDataTests.``All succeeds`` (mkData ())
|
||||
}
|
||||
testTask "CountAll succeeds" {
|
||||
do! PageDataTests.``CountAll succeeds`` (mkData ())
|
||||
}
|
||||
testTask "CountListed succeeds" {
|
||||
do! PageDataTests.``CountListed succeeds`` (mkData ())
|
||||
}
|
||||
testList "FindById" [
|
||||
testTask "succeeds when a page is found" {
|
||||
do! PageDataTests.``FindById succeeds when a page is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a page is not found (incorrect weblog)" {
|
||||
do! PageDataTests.``FindById succeeds when a page is not found (incorrect weblog)`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a page is not found (bad page ID)" {
|
||||
do! PageDataTests.``FindById succeeds when a page is not found (bad page ID)`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindByPermalink" [
|
||||
testTask "succeeds when a page is found" {
|
||||
do! PageDataTests.``FindByPermalink succeeds when a page is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a page is not found (incorrect weblog)" {
|
||||
do! PageDataTests.``FindByPermalink succeeds when a page is not found (incorrect weblog)`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a page is not found (no such permalink)" {
|
||||
do! PageDataTests.``FindByPermalink succeeds when a page is not found (no such permalink)`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindCurrentPermalink" [
|
||||
testTask "succeeds when a page is found" {
|
||||
do! PageDataTests.``FindCurrentPermalink succeeds when a page is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a page is not found" {
|
||||
do! PageDataTests.``FindCurrentPermalink succeeds when a page is not found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindFullById" [
|
||||
testTask "succeeds when a page is found" {
|
||||
do! PageDataTests.``FindFullById succeeds when a page is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a page is not found" {
|
||||
do! PageDataTests.``FindFullById succeeds when a page is not found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindFullByWebLog" [
|
||||
testTask "succeeds when pages are found" {
|
||||
do! PageDataTests.``FindFullByWebLog succeeds when pages are found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a pages are not found" {
|
||||
do! PageDataTests.``FindFullByWebLog succeeds when pages are not found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindListed" [
|
||||
testTask "succeeds when pages are found" {
|
||||
do! PageDataTests.``FindListed succeeds when pages are found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a pages are not found" {
|
||||
do! PageDataTests.``FindListed succeeds when pages are not found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindPageOfPages" [
|
||||
testTask "succeeds when pages are found" {
|
||||
do! PageDataTests.``FindPageOfPages succeeds when pages are found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a pages are not found" {
|
||||
do! PageDataTests.``FindPageOfPages succeeds when pages are not found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "Update" [
|
||||
testTask "succeeds when the page exists" {
|
||||
do! PageDataTests.``Update succeeds when the page exists`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the page does not exist" {
|
||||
do! PageDataTests.``Update succeeds when the page does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "UpdatePriorPermalinks" [
|
||||
testTask "succeeds when the page exists" {
|
||||
do! PageDataTests.``UpdatePriorPermalinks succeeds when the page exists`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the page does not exist" {
|
||||
do! PageDataTests.``UpdatePriorPermalinks succeeds when the page does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "succeeds when a page is deleted" {
|
||||
do! PageDataTests.``Delete succeeds when a page is deleted`` (mkData ())
|
||||
let! revisions =
|
||||
Custom.scalar
|
||||
"SELECT COUNT(*) AS it FROM page_revision WHERE page_id = @id"
|
||||
[ idParam PageDataTests.coolPageId ]
|
||||
toCount
|
||||
Expect.equal revisions 0 "All revisions for the page should have been deleted"
|
||||
}
|
||||
testTask "succeeds when a page is not deleted" {
|
||||
do! PageDataTests.``Delete succeeds when a page is not deleted`` (mkData ())
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Integration tests for the Post implementation in PostgreSQL
|
||||
let private postTests = testList "Post" [
|
||||
testTask "Add succeeds" {
|
||||
// We'll need the root website categories restored for these tests
|
||||
do! freshEnvironment ()
|
||||
do! PostDataTests.``Add succeeds`` (mkData ())
|
||||
}
|
||||
testTask "CountByStatus succeeds" {
|
||||
do! PostDataTests.``CountByStatus succeeds`` (mkData ())
|
||||
}
|
||||
testList "FindById" [
|
||||
testTask "succeeds when a post is found" {
|
||||
do! PostDataTests.``FindById succeeds when a post is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a post is not found (incorrect weblog)" {
|
||||
do! PostDataTests.``FindById succeeds when a post is not found (incorrect weblog)`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a post is not found (bad post ID)" {
|
||||
do! PostDataTests.``FindById succeeds when a post is not found (bad post ID)`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindByPermalink" [
|
||||
testTask "succeeds when a post is found" {
|
||||
do! PostDataTests.``FindByPermalink succeeds when a post is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a post is not found (incorrect weblog)" {
|
||||
do! PostDataTests.``FindByPermalink succeeds when a post is not found (incorrect weblog)`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a post is not found (no such permalink)" {
|
||||
do! PostDataTests.``FindByPermalink succeeds when a post is not found (no such permalink)`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindCurrentPermalink" [
|
||||
testTask "succeeds when a post is found" {
|
||||
do! PostDataTests.``FindCurrentPermalink succeeds when a post is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a post is not found" {
|
||||
do! PostDataTests.``FindCurrentPermalink succeeds when a post is not found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindFullById" [
|
||||
testTask "succeeds when a post is found" {
|
||||
do! PostDataTests.``FindFullById succeeds when a post is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a post is not found" {
|
||||
do! PostDataTests.``FindFullById succeeds when a post is not found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindFullByWebLog" [
|
||||
testTask "succeeds when posts are found" {
|
||||
do! PostDataTests.``FindFullByWebLog succeeds when posts are found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a posts are not found" {
|
||||
do! PostDataTests.``FindFullByWebLog succeeds when posts are not found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindPageOfCategorizedPosts" [
|
||||
testTask "succeeds when posts are found" {
|
||||
do! PostDataTests.``FindPageOfCategorizedPosts succeeds when posts are found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when finding a too-high page number" {
|
||||
do! PostDataTests.``FindPageOfCategorizedPosts succeeds when finding a too-high page number`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a category has no posts" {
|
||||
do! PostDataTests.``FindPageOfCategorizedPosts succeeds when a category has no posts`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindPageOfPosts" [
|
||||
testTask "succeeds when posts are found" {
|
||||
do! PostDataTests.``FindPageOfPosts succeeds when posts are found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when finding a too-high page number" {
|
||||
do! PostDataTests.``FindPageOfPosts succeeds when finding a too-high page number`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when there are no posts" {
|
||||
do! PostDataTests.``FindPageOfPosts succeeds when there are no posts`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindPageOfPublishedPosts" [
|
||||
testTask "succeeds when posts are found" {
|
||||
do! PostDataTests.``FindPageOfPublishedPosts succeeds when posts are found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when finding a too-high page number" {
|
||||
do! PostDataTests.``FindPageOfPublishedPosts succeeds when finding a too-high page number`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when there are no posts" {
|
||||
do! PostDataTests.``FindPageOfPublishedPosts succeeds when there are no posts`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindPageOfTaggedPosts" [
|
||||
testTask "succeeds when posts are found" {
|
||||
do! PostDataTests.``FindPageOfTaggedPosts succeeds when posts are found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when posts are found (excluding drafts)" {
|
||||
do! PostDataTests.``FindPageOfTaggedPosts succeeds when posts are found (excluding drafts)`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when finding a too-high page number" {
|
||||
do! PostDataTests.``FindPageOfTaggedPosts succeeds when finding a too-high page number`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when there are no posts" {
|
||||
do! PostDataTests.``FindPageOfTaggedPosts succeeds when there are no posts`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindSurroundingPosts" [
|
||||
testTask "succeeds when there is no next newer post" {
|
||||
do! PostDataTests.``FindSurroundingPosts succeeds when there is no next newer post`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when there is no next older post" {
|
||||
do! PostDataTests.``FindSurroundingPosts succeeds when there is no next older post`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when older and newer exist" {
|
||||
do! PostDataTests.``FindSurroundingPosts succeeds when older and newer exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "Update" [
|
||||
testTask "succeeds when the post exists" {
|
||||
do! PostDataTests.``Update succeeds when the post exists`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the post does not exist" {
|
||||
do! PostDataTests.``Update succeeds when the post does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "UpdatePriorPermalinks" [
|
||||
testTask "succeeds when the post exists" {
|
||||
do! PostDataTests.``UpdatePriorPermalinks succeeds when the post exists`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the post does not exist" {
|
||||
do! PostDataTests.``UpdatePriorPermalinks succeeds when the post does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "succeeds when a post is deleted" {
|
||||
do! PostDataTests.``Delete succeeds when a post is deleted`` (mkData ())
|
||||
let! revisions =
|
||||
Custom.scalar
|
||||
"SELECT COUNT(*) AS it FROM post_revision WHERE post_id = @id"
|
||||
[ idParam PostDataTests.episode2 ]
|
||||
toCount
|
||||
Expect.equal revisions 0 "All revisions for the post should have been deleted"
|
||||
}
|
||||
testTask "succeeds when a post is not deleted" {
|
||||
do! PostDataTests.``Delete succeeds when a post is not deleted`` (mkData ())
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
let private tagMapTests = testList "TagMap" [
|
||||
testList "FindById" [
|
||||
testTask "succeeds when a tag mapping is found" {
|
||||
do! TagMapDataTests.``FindById succeeds when a tag mapping is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a tag mapping is not found (incorrect weblog)" {
|
||||
do! TagMapDataTests.``FindById succeeds when a tag mapping is not found (incorrect weblog)`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a tag mapping is not found (bad tag map ID)" {
|
||||
do! TagMapDataTests.``FindById succeeds when a tag mapping is not found (bad tag map ID)`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindByUrlValue" [
|
||||
testTask "succeeds when a tag mapping is found" {
|
||||
do! TagMapDataTests.``FindByUrlValue succeeds when a tag mapping is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a tag mapping is not found (incorrect weblog)" {
|
||||
do! TagMapDataTests.``FindByUrlValue succeeds when a tag mapping is not found (incorrect weblog)``
|
||||
(mkData ())
|
||||
}
|
||||
testTask "succeeds when a tag mapping is not found (no such value)" {
|
||||
do! TagMapDataTests.``FindByUrlValue succeeds when a tag mapping is not found (no such value)`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindByWebLog" [
|
||||
testTask "succeeds when tag mappings are found" {
|
||||
do! TagMapDataTests.``FindByWebLog succeeds when tag mappings are found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when no tag mappings are found" {
|
||||
do! TagMapDataTests.``FindByWebLog succeeds when no tag mappings are found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindMappingForTags" [
|
||||
testTask "succeeds when mappings exist" {
|
||||
do! TagMapDataTests.``FindMappingForTags succeeds when mappings exist`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when no mappings exist" {
|
||||
do! TagMapDataTests.``FindMappingForTags succeeds when no mappings exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "Save" [
|
||||
testTask "succeeds when adding a tag mapping" {
|
||||
do! TagMapDataTests.``Save succeeds when adding a tag mapping`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when updating a tag mapping" {
|
||||
do! TagMapDataTests.``Save succeeds when updating a tag mapping`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "succeeds when a tag mapping is deleted" {
|
||||
do! TagMapDataTests.``Delete succeeds when a tag mapping is deleted`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a tag mapping is not deleted" {
|
||||
do! TagMapDataTests.``Delete succeeds when a tag mapping is not deleted`` (mkData ())
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
let private themeTests = testList "Theme" [
|
||||
testTask "All succeeds" {
|
||||
do! ThemeDataTests.``All succeeds`` (mkData ())
|
||||
}
|
||||
testList "Exists" [
|
||||
testTask "succeeds when the theme exists" {
|
||||
do! ThemeDataTests.``Exists succeeds when the theme exists`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the theme does not exist" {
|
||||
do! ThemeDataTests.``Exists succeeds when the theme does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindById" [
|
||||
testTask "succeeds when the theme exists" {
|
||||
do! ThemeDataTests.``FindById succeeds when the theme exists`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the theme does not exist" {
|
||||
do! ThemeDataTests.``FindById succeeds when the theme does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindByIdWithoutText" [
|
||||
testTask "succeeds when the theme exists" {
|
||||
do! ThemeDataTests.``FindByIdWithoutText succeeds when the theme exists`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the theme does not exist" {
|
||||
do! ThemeDataTests.``FindByIdWithoutText succeeds when the theme does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "Save" [
|
||||
testTask "succeeds when adding a theme" {
|
||||
do! ThemeDataTests.``Save succeeds when adding a theme`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when updating a theme" {
|
||||
do! ThemeDataTests.``Save succeeds when updating a theme`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "succeeds when a theme is deleted" {
|
||||
do! ThemeDataTests.``Delete succeeds when a theme is deleted`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a theme is not deleted" {
|
||||
do! ThemeDataTests.``Delete succeeds when a theme is not deleted`` (mkData ())
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
let private themeAssetTests = testList "ThemeAsset" [
|
||||
testList "Save" [
|
||||
testTask "succeeds when adding an asset" {
|
||||
do! ThemeDataTests.Asset.``Save succeeds when adding an asset`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when updating an asset" {
|
||||
do! ThemeDataTests.Asset.``Save succeeds when updating an asset`` (mkData ())
|
||||
}
|
||||
]
|
||||
testTask "All succeeds" {
|
||||
do! ThemeDataTests.Asset.``All succeeds`` (mkData ())
|
||||
}
|
||||
testList "FindById" [
|
||||
testTask "succeeds when an asset is found" {
|
||||
do! ThemeDataTests.Asset.``FindById succeeds when an asset is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when an asset is not found" {
|
||||
do! ThemeDataTests.Asset.``FindById succeeds when an asset is not found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindByTheme" [
|
||||
testTask "succeeds when assets exist" {
|
||||
do! ThemeDataTests.Asset.``FindByTheme succeeds when assets exist`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when assets do not exist" {
|
||||
do! ThemeDataTests.Asset.``FindByTheme succeeds when assets do not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindByThemeWithData" [
|
||||
testTask "succeeds when assets exist" {
|
||||
do! ThemeDataTests.Asset.``FindByThemeWithData succeeds when assets exist`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when assets do not exist" {
|
||||
do! ThemeDataTests.Asset.``FindByThemeWithData succeeds when assets do not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "DeleteByTheme" [
|
||||
testTask "succeeds when assets are deleted" {
|
||||
do! ThemeDataTests.Asset.``DeleteByTheme succeeds when assets are deleted`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when no assets are deleted" {
|
||||
do! ThemeDataTests.Asset.``DeleteByTheme succeeds when no assets are deleted`` (mkData ())
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
let private uploadTests = testList "Upload" [
|
||||
testTask "Add succeeds" {
|
||||
do! UploadDataTests.``Add succeeds`` (mkData ())
|
||||
}
|
||||
testList "FindByPath" [
|
||||
testTask "succeeds when an upload is found" {
|
||||
do! UploadDataTests.``FindByPath succeeds when an upload is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when an upload is not found (incorrect weblog)" {
|
||||
do! UploadDataTests.``FindByPath succeeds when an upload is not found (incorrect weblog)`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when an upload is not found (bad path)" {
|
||||
do! UploadDataTests.``FindByPath succeeds when an upload is not found (bad path)`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindByWebLog" [
|
||||
testTask "succeeds when uploads exist" {
|
||||
do! UploadDataTests.``FindByWebLog succeeds when uploads exist`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when no uploads exist" {
|
||||
do! UploadDataTests.``FindByWebLog succeeds when no uploads exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindByWebLogWithData" [
|
||||
testTask "succeeds when uploads exist" {
|
||||
do! UploadDataTests.``FindByWebLogWithData succeeds when uploads exist`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when no uploads exist" {
|
||||
do! UploadDataTests.``FindByWebLogWithData succeeds when no uploads exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "succeeds when an upload is deleted" {
|
||||
do! UploadDataTests.``Delete succeeds when an upload is deleted`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when an upload is not deleted" {
|
||||
do! UploadDataTests.``Delete succeeds when an upload is not deleted`` (mkData ())
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
let private webLogUserTests = testList "WebLogUser" [
|
||||
testTask "Add succeeds" {
|
||||
// This restore ensures all the posts and pages exist
|
||||
do! freshEnvironment ()
|
||||
do! WebLogUserDataTests.``Add succeeds`` (mkData ())
|
||||
}
|
||||
testList "FindByEmail" [
|
||||
testTask "succeeds when a user is found" {
|
||||
do! WebLogUserDataTests.``FindByEmail succeeds when a user is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a user is not found (incorrect weblog)" {
|
||||
do! WebLogUserDataTests.``FindByEmail succeeds when a user is not found (incorrect weblog)`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a user is not found (bad email)" {
|
||||
do! WebLogUserDataTests.``FindByEmail succeeds when a user is not found (bad email)`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindById" [
|
||||
testTask "succeeds when a user is found" {
|
||||
do! WebLogUserDataTests.``FindById succeeds when a user is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a user is not found (incorrect weblog)" {
|
||||
do! WebLogUserDataTests.``FindById succeeds when a user is not found (incorrect weblog)`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a user is not found (bad ID)" {
|
||||
do! WebLogUserDataTests.``FindById succeeds when a user is not found (bad ID)`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindByWebLog" [
|
||||
testTask "succeeds when users exist" {
|
||||
do! WebLogUserDataTests.``FindByWebLog succeeds when users exist`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when no users exist" {
|
||||
do! WebLogUserDataTests.``FindByWebLog succeeds when no users exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindNames" [
|
||||
testTask "succeeds when users exist" {
|
||||
do! WebLogUserDataTests.``FindNames succeeds when users exist`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when users do not exist" {
|
||||
do! WebLogUserDataTests.``FindNames succeeds when users do not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "SetLastSeen" [
|
||||
testTask "succeeds when the user exists" {
|
||||
do! WebLogUserDataTests.``SetLastSeen succeeds when the user exists`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the user does not exist" {
|
||||
do! WebLogUserDataTests.``SetLastSeen succeeds when the user does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "Update" [
|
||||
testTask "succeeds when the user exists" {
|
||||
do! WebLogUserDataTests.``Update succeeds when the user exists`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the user does not exist" {
|
||||
do! WebLogUserDataTests.``Update succeeds when the user does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "fails when the user is the author of a page" {
|
||||
do! WebLogUserDataTests.``Delete fails when the user is the author of a page`` (mkData ())
|
||||
}
|
||||
testTask "fails when the user is the author of a post" {
|
||||
do! WebLogUserDataTests.``Delete fails when the user is the author of a post`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the user is not an author" {
|
||||
do! WebLogUserDataTests.``Delete succeeds when the user is not an author`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the user does not exist" {
|
||||
do! WebLogUserDataTests.``Delete succeeds when the user does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
let private webLogTests = testList "WebLog" [
|
||||
testTask "Add succeeds" {
|
||||
do! WebLogDataTests.``Add succeeds`` (mkData ())
|
||||
}
|
||||
testTask "All succeeds" {
|
||||
do! WebLogDataTests.``All succeeds`` (mkData ())
|
||||
}
|
||||
testList "FindByHost" [
|
||||
testTask "succeeds when a web log is found" {
|
||||
do! WebLogDataTests.``FindByHost succeeds when a web log is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a web log is not found" {
|
||||
do! WebLogDataTests.``FindByHost succeeds when a web log is not found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "FindById" [
|
||||
testTask "succeeds when a web log is found" {
|
||||
do! WebLogDataTests.``FindById succeeds when a web log is found`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when a web log is not found" {
|
||||
do! WebLogDataTests.``FindById succeeds when a web log is not found`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "UpdateRedirectRules" [
|
||||
testTask "succeeds when the web log exists" {
|
||||
do! WebLogDataTests.``UpdateRedirectRules succeeds when the web log exists`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the web log does not exist" {
|
||||
do! WebLogDataTests.``UpdateRedirectRules succeeds when the web log does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "UpdateRssOptions" [
|
||||
testTask "succeeds when the web log exists" {
|
||||
do! WebLogDataTests.``UpdateRssOptions succeeds when the web log exists`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the web log does not exist" {
|
||||
do! WebLogDataTests.``UpdateRssOptions succeeds when the web log does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "UpdateSettings" [
|
||||
testTask "succeeds when the web log exists" {
|
||||
do! WebLogDataTests.``UpdateSettings succeeds when the web log exists`` (mkData ())
|
||||
}
|
||||
testTask "succeeds when the web log does not exist" {
|
||||
do! WebLogDataTests.``UpdateSettings succeeds when the web log does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "succeeds when the web log exists" {
|
||||
do! WebLogDataTests.``Delete succeeds when the web log exists`` (mkData ())
|
||||
let! revisions =
|
||||
Custom.scalar
|
||||
"SELECT (SELECT COUNT(*) FROM page_revision) + (SELECT COUNT(*) FROM post_revision) AS it"
|
||||
[]
|
||||
toCount
|
||||
Expect.equal revisions 0 "All revisions should be deleted"
|
||||
}
|
||||
testTask "succeeds when the web log does not exist" {
|
||||
do! WebLogDataTests.``Delete succeeds when the web log does not exist`` (mkData ())
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Drop the throwaway PostgreSQL database
|
||||
let private environmentCleanUp = test "Clean Up" {
|
||||
if db.IsSome then db.Value.Dispose()
|
||||
}
|
||||
|
||||
/// All PostgreSQL data tests
|
||||
let all =
|
||||
testList "PostgresData"
|
||||
[ environmentSetUp
|
||||
categoryTests
|
||||
pageTests
|
||||
postTests
|
||||
tagMapTests
|
||||
themeTests
|
||||
themeAssetTests
|
||||
uploadTests
|
||||
webLogUserTests
|
||||
webLogTests
|
||||
environmentCleanUp ]
|
||||
|> testSequenced
|
||||
704
src/MyWebLog.Tests/Data/RethinkDbDataTests.fs
Normal file
704
src/MyWebLog.Tests/Data/RethinkDbDataTests.fs
Normal file
@@ -0,0 +1,704 @@
|
||||
module RethinkDbDataTests
|
||||
|
||||
open System
|
||||
open Expecto
|
||||
open Microsoft.Extensions.Logging.Abstractions
|
||||
open MyWebLog
|
||||
open MyWebLog.Converters
|
||||
open MyWebLog.Data
|
||||
open RethinkDb.Driver.FSharp
|
||||
open RethinkDb.Driver.Net
|
||||
|
||||
/// Get an environment variable, using the given value as the default if it is not set
|
||||
let env name value =
|
||||
match Environment.GetEnvironmentVariable $"MWL_TEST_{name}" with
|
||||
| null -> value
|
||||
| it when it.Trim() = "" -> value
|
||||
| it -> it
|
||||
|
||||
|
||||
/// The data configuration for the test database
|
||||
let private dataCfg =
|
||||
DataConfig.FromUri (env "RETHINK_URI" "rethinkdb://172.17.0.2/mwl_test")
|
||||
|
||||
/// The active data instance to use for testing
|
||||
let mutable private data: IData option = None
|
||||
|
||||
/// Dispose the existing data
|
||||
let private disposeData () = task {
|
||||
if data.IsSome then
|
||||
let conn = (data.Value :?> RethinkDbData).Conn
|
||||
do! rethink { dbDrop dataCfg.Database; write; withRetryOnce; ignoreResult conn }
|
||||
conn.Dispose()
|
||||
data <- None
|
||||
}
|
||||
|
||||
/// Create a new data implementation instance
|
||||
let private newData () =
|
||||
let log = NullLogger<RethinkDbData>()
|
||||
let conn = dataCfg.CreateConnection log
|
||||
RethinkDbData(conn, dataCfg, log)
|
||||
|
||||
/// Create a fresh environment from the root backup
|
||||
let private freshEnvironment () = task {
|
||||
do! disposeData ()
|
||||
data <- Some (newData ())
|
||||
do! data.Value.StartUp()
|
||||
// This exercises Restore for all implementations; all tests are dependent on it working as expected
|
||||
do! Maintenance.Backup.restoreBackup "root-weblog.json" None false false data.Value
|
||||
}
|
||||
|
||||
/// Set up the environment for the RethinkDB tests
|
||||
let private environmentSetUp = testTask "creating database" {
|
||||
let _ = Json.configure Converter.Serializer
|
||||
do! freshEnvironment ()
|
||||
}
|
||||
|
||||
/// Integration tests for the Category implementation in RethinkDB
|
||||
let private categoryTests = testList "Category" [
|
||||
testTask "Add succeeds" {
|
||||
do! CategoryDataTests.``Add succeeds`` data.Value
|
||||
}
|
||||
testList "CountAll" [
|
||||
testTask "succeeds when categories exist" {
|
||||
do! CategoryDataTests.``CountAll succeeds when categories exist`` data.Value
|
||||
}
|
||||
testTask "succeeds when categories do not exist" {
|
||||
do! CategoryDataTests.``CountAll succeeds when categories do not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "CountTopLevel" [
|
||||
testTask "succeeds when top-level categories exist" {
|
||||
do! CategoryDataTests.``CountTopLevel succeeds when top-level categories exist`` data.Value
|
||||
}
|
||||
testTask "succeeds when no top-level categories exist" {
|
||||
do! CategoryDataTests.``CountTopLevel succeeds when no top-level categories exist`` data.Value
|
||||
}
|
||||
]
|
||||
testTask "FindAllForView succeeds" {
|
||||
do! CategoryDataTests.``FindAllForView succeeds`` data.Value
|
||||
}
|
||||
testList "FindById" [
|
||||
testTask "succeeds when a category is found" {
|
||||
do! CategoryDataTests.``FindById succeeds when a category is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a category is not found" {
|
||||
do! CategoryDataTests.``FindById succeeds when a category is not found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindByWebLog" [
|
||||
testTask "succeeds when categories exist" {
|
||||
do! CategoryDataTests.``FindByWebLog succeeds when categories exist`` data.Value
|
||||
}
|
||||
testTask "succeeds when no categories exist" {
|
||||
do! CategoryDataTests.``FindByWebLog succeeds when no categories exist`` data.Value
|
||||
}
|
||||
]
|
||||
testTask "Update succeeds" {
|
||||
do! CategoryDataTests.``Update succeeds`` data.Value
|
||||
}
|
||||
testList "Delete" [
|
||||
testTask "succeeds when the category is deleted (no posts)" {
|
||||
do! CategoryDataTests.``Delete succeeds when the category is deleted (no posts)`` data.Value
|
||||
}
|
||||
testTask "succeeds when the category does not exist" {
|
||||
do! CategoryDataTests.``Delete succeeds when the category does not exist`` data.Value
|
||||
}
|
||||
testTask "succeeds when reassigning parent category to None" {
|
||||
do! CategoryDataTests.``Delete succeeds when reassigning parent category to None`` data.Value
|
||||
}
|
||||
testTask "succeeds when reassigning parent category to Some" {
|
||||
do! CategoryDataTests.``Delete succeeds when reassigning parent category to Some`` data.Value
|
||||
}
|
||||
testTask "succeeds and removes category from posts" {
|
||||
do! CategoryDataTests.``Delete succeeds and removes category from posts`` data.Value
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Integration tests for the Page implementation in RethinkDB
|
||||
let private pageTests = testList "Page" [
|
||||
testTask "Add succeeds" {
|
||||
do! PageDataTests.``Add succeeds`` data.Value
|
||||
}
|
||||
testTask "All succeeds" {
|
||||
do! PageDataTests.``All succeeds`` data.Value
|
||||
}
|
||||
testTask "CountAll succeeds" {
|
||||
do! PageDataTests.``CountAll succeeds`` data.Value
|
||||
}
|
||||
testTask "CountListed succeeds" {
|
||||
do! PageDataTests.``CountListed succeeds`` data.Value
|
||||
}
|
||||
testList "FindById" [
|
||||
testTask "succeeds when a page is found" {
|
||||
do! PageDataTests.``FindById succeeds when a page is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a page is not found (incorrect weblog)" {
|
||||
do! PageDataTests.``FindById succeeds when a page is not found (incorrect weblog)`` data.Value
|
||||
}
|
||||
testTask "succeeds when a page is not found (bad page ID)" {
|
||||
do! PageDataTests.``FindById succeeds when a page is not found (bad page ID)`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindByPermalink" [
|
||||
testTask "succeeds when a page is found" {
|
||||
do! PageDataTests.``FindByPermalink succeeds when a page is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a page is not found (incorrect weblog)" {
|
||||
do! PageDataTests.``FindByPermalink succeeds when a page is not found (incorrect weblog)`` data.Value
|
||||
}
|
||||
testTask "succeeds when a page is not found (no such permalink)" {
|
||||
do! PageDataTests.``FindByPermalink succeeds when a page is not found (no such permalink)`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindCurrentPermalink" [
|
||||
testTask "succeeds when a page is found" {
|
||||
do! PageDataTests.``FindCurrentPermalink succeeds when a page is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a page is not found" {
|
||||
do! PageDataTests.``FindCurrentPermalink succeeds when a page is not found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindFullById" [
|
||||
testTask "succeeds when a page is found" {
|
||||
do! PageDataTests.``FindFullById succeeds when a page is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a page is not found" {
|
||||
do! PageDataTests.``FindFullById succeeds when a page is not found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindFullByWebLog" [
|
||||
testTask "succeeds when pages are found" {
|
||||
do! PageDataTests.``FindFullByWebLog succeeds when pages are found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a pages are not found" {
|
||||
do! PageDataTests.``FindFullByWebLog succeeds when pages are not found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindListed" [
|
||||
testTask "succeeds when pages are found" {
|
||||
do! PageDataTests.``FindListed succeeds when pages are found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a pages are not found" {
|
||||
do! PageDataTests.``FindListed succeeds when pages are not found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindPageOfPages" [
|
||||
testTask "succeeds when pages are found" {
|
||||
do! PageDataTests.``FindPageOfPages succeeds when pages are found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a pages are not found" {
|
||||
do! PageDataTests.``FindPageOfPages succeeds when pages are not found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "Update" [
|
||||
testTask "succeeds when the page exists" {
|
||||
do! PageDataTests.``Update succeeds when the page exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the page does not exist" {
|
||||
do! PageDataTests.``Update succeeds when the page does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "UpdatePriorPermalinks" [
|
||||
testTask "succeeds when the page exists" {
|
||||
do! PageDataTests.``UpdatePriorPermalinks succeeds when the page exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the page does not exist" {
|
||||
do! PageDataTests.``UpdatePriorPermalinks succeeds when the page does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "succeeds when a page is deleted" {
|
||||
do! PageDataTests.``Delete succeeds when a page is deleted`` data.Value
|
||||
}
|
||||
testTask "succeeds when a page is not deleted" {
|
||||
do! PageDataTests.``Delete succeeds when a page is not deleted`` data.Value
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Integration tests for the Post implementation in RethinkDB
|
||||
let private postTests = testList "Post" [
|
||||
testTask "Add succeeds" {
|
||||
// We'll need the root website categories restored for these tests
|
||||
do! freshEnvironment ()
|
||||
do! PostDataTests.``Add succeeds`` data.Value
|
||||
}
|
||||
testTask "CountByStatus succeeds" {
|
||||
do! PostDataTests.``CountByStatus succeeds`` data.Value
|
||||
}
|
||||
testList "FindById" [
|
||||
testTask "succeeds when a post is found" {
|
||||
do! PostDataTests.``FindById succeeds when a post is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a post is not found (incorrect weblog)" {
|
||||
do! PostDataTests.``FindById succeeds when a post is not found (incorrect weblog)`` data.Value
|
||||
}
|
||||
testTask "succeeds when a post is not found (bad post ID)" {
|
||||
do! PostDataTests.``FindById succeeds when a post is not found (bad post ID)`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindByPermalink" [
|
||||
testTask "succeeds when a post is found" {
|
||||
do! PostDataTests.``FindByPermalink succeeds when a post is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a post is not found (incorrect weblog)" {
|
||||
do! PostDataTests.``FindByPermalink succeeds when a post is not found (incorrect weblog)`` data.Value
|
||||
}
|
||||
testTask "succeeds when a post is not found (no such permalink)" {
|
||||
do! PostDataTests.``FindByPermalink succeeds when a post is not found (no such permalink)`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindCurrentPermalink" [
|
||||
testTask "succeeds when a post is found" {
|
||||
do! PostDataTests.``FindCurrentPermalink succeeds when a post is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a post is not found" {
|
||||
do! PostDataTests.``FindCurrentPermalink succeeds when a post is not found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindFullById" [
|
||||
testTask "succeeds when a post is found" {
|
||||
do! PostDataTests.``FindFullById succeeds when a post is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a post is not found" {
|
||||
do! PostDataTests.``FindFullById succeeds when a post is not found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindFullByWebLog" [
|
||||
testTask "succeeds when posts are found" {
|
||||
do! PostDataTests.``FindFullByWebLog succeeds when posts are found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a posts are not found" {
|
||||
do! PostDataTests.``FindFullByWebLog succeeds when posts are not found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindPageOfCategorizedPosts" [
|
||||
testTask "succeeds when posts are found" {
|
||||
do! PostDataTests.``FindPageOfCategorizedPosts succeeds when posts are found`` data.Value
|
||||
}
|
||||
testTask "succeeds when finding a too-high page number" {
|
||||
do! PostDataTests.``FindPageOfCategorizedPosts succeeds when finding a too-high page number`` data.Value
|
||||
}
|
||||
testTask "succeeds when a category has no posts" {
|
||||
do! PostDataTests.``FindPageOfCategorizedPosts succeeds when a category has no posts`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindPageOfPosts" [
|
||||
testTask "succeeds when posts are found" {
|
||||
do! PostDataTests.``FindPageOfPosts succeeds when posts are found`` data.Value
|
||||
}
|
||||
testTask "succeeds when finding a too-high page number" {
|
||||
do! PostDataTests.``FindPageOfPosts succeeds when finding a too-high page number`` data.Value
|
||||
}
|
||||
testTask "succeeds when there are no posts" {
|
||||
do! PostDataTests.``FindPageOfPosts succeeds when there are no posts`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindPageOfPublishedPosts" [
|
||||
testTask "succeeds when posts are found" {
|
||||
do! PostDataTests.``FindPageOfPublishedPosts succeeds when posts are found`` data.Value
|
||||
}
|
||||
testTask "succeeds when finding a too-high page number" {
|
||||
do! PostDataTests.``FindPageOfPublishedPosts succeeds when finding a too-high page number`` data.Value
|
||||
}
|
||||
testTask "succeeds when there are no posts" {
|
||||
do! PostDataTests.``FindPageOfPublishedPosts succeeds when there are no posts`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindPageOfTaggedPosts" [
|
||||
testTask "succeeds when posts are found" {
|
||||
do! PostDataTests.``FindPageOfTaggedPosts succeeds when posts are found`` data.Value
|
||||
}
|
||||
testTask "succeeds when posts are found (excluding drafts)" {
|
||||
do! PostDataTests.``FindPageOfTaggedPosts succeeds when posts are found (excluding drafts)`` data.Value
|
||||
}
|
||||
testTask "succeeds when finding a too-high page number" {
|
||||
do! PostDataTests.``FindPageOfTaggedPosts succeeds when finding a too-high page number`` data.Value
|
||||
}
|
||||
testTask "succeeds when there are no posts" {
|
||||
do! PostDataTests.``FindPageOfTaggedPosts succeeds when there are no posts`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindSurroundingPosts" [
|
||||
testTask "succeeds when there is no next newer post" {
|
||||
do! PostDataTests.``FindSurroundingPosts succeeds when there is no next newer post`` data.Value
|
||||
}
|
||||
testTask "succeeds when there is no next older post" {
|
||||
do! PostDataTests.``FindSurroundingPosts succeeds when there is no next older post`` data.Value
|
||||
}
|
||||
testTask "succeeds when older and newer exist" {
|
||||
do! PostDataTests.``FindSurroundingPosts succeeds when older and newer exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "Update" [
|
||||
testTask "succeeds when the post exists" {
|
||||
do! PostDataTests.``Update succeeds when the post exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the post does not exist" {
|
||||
do! PostDataTests.``Update succeeds when the post does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "UpdatePriorPermalinks" [
|
||||
testTask "succeeds when the post exists" {
|
||||
do! PostDataTests.``UpdatePriorPermalinks succeeds when the post exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the post does not exist" {
|
||||
do! PostDataTests.``UpdatePriorPermalinks succeeds when the post does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "succeeds when a post is deleted" {
|
||||
do! PostDataTests.``Delete succeeds when a post is deleted`` data.Value
|
||||
}
|
||||
testTask "succeeds when a post is not deleted" {
|
||||
do! PostDataTests.``Delete succeeds when a post is not deleted`` data.Value
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
let private tagMapTests = testList "TagMap" [
|
||||
testList "FindById" [
|
||||
testTask "succeeds when a tag mapping is found" {
|
||||
do! TagMapDataTests.``FindById succeeds when a tag mapping is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a tag mapping is not found (incorrect weblog)" {
|
||||
do! TagMapDataTests.``FindById succeeds when a tag mapping is not found (incorrect weblog)`` data.Value
|
||||
}
|
||||
testTask "succeeds when a tag mapping is not found (bad tag map ID)" {
|
||||
do! TagMapDataTests.``FindById succeeds when a tag mapping is not found (bad tag map ID)`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindByUrlValue" [
|
||||
testTask "succeeds when a tag mapping is found" {
|
||||
do! TagMapDataTests.``FindByUrlValue succeeds when a tag mapping is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a tag mapping is not found (incorrect weblog)" {
|
||||
do! TagMapDataTests.``FindByUrlValue succeeds when a tag mapping is not found (incorrect weblog)``
|
||||
data.Value
|
||||
}
|
||||
testTask "succeeds when a tag mapping is not found (no such value)" {
|
||||
do! TagMapDataTests.``FindByUrlValue succeeds when a tag mapping is not found (no such value)`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindByWebLog" [
|
||||
testTask "succeeds when tag mappings are found" {
|
||||
do! TagMapDataTests.``FindByWebLog succeeds when tag mappings are found`` data.Value
|
||||
}
|
||||
testTask "succeeds when no tag mappings are found" {
|
||||
do! TagMapDataTests.``FindByWebLog succeeds when no tag mappings are found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindMappingForTags" [
|
||||
testTask "succeeds when mappings exist" {
|
||||
do! TagMapDataTests.``FindMappingForTags succeeds when mappings exist`` data.Value
|
||||
}
|
||||
testTask "succeeds when no mappings exist" {
|
||||
do! TagMapDataTests.``FindMappingForTags succeeds when no mappings exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "Save" [
|
||||
testTask "succeeds when adding a tag mapping" {
|
||||
do! TagMapDataTests.``Save succeeds when adding a tag mapping`` data.Value
|
||||
}
|
||||
testTask "succeeds when updating a tag mapping" {
|
||||
do! TagMapDataTests.``Save succeeds when updating a tag mapping`` data.Value
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "succeeds when a tag mapping is deleted" {
|
||||
do! TagMapDataTests.``Delete succeeds when a tag mapping is deleted`` data.Value
|
||||
}
|
||||
testTask "succeeds when a tag mapping is not deleted" {
|
||||
do! TagMapDataTests.``Delete succeeds when a tag mapping is not deleted`` data.Value
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
let private themeTests = testList "Theme" [
|
||||
testTask "All succeeds" {
|
||||
do! ThemeDataTests.``All succeeds`` data.Value
|
||||
}
|
||||
testList "Exists" [
|
||||
testTask "succeeds when the theme exists" {
|
||||
do! ThemeDataTests.``Exists succeeds when the theme exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the theme does not exist" {
|
||||
do! ThemeDataTests.``Exists succeeds when the theme does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindById" [
|
||||
testTask "succeeds when the theme exists" {
|
||||
do! ThemeDataTests.``FindById succeeds when the theme exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the theme does not exist" {
|
||||
do! ThemeDataTests.``FindById succeeds when the theme does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindByIdWithoutText" [
|
||||
testTask "succeeds when the theme exists" {
|
||||
do! ThemeDataTests.``FindByIdWithoutText succeeds when the theme exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the theme does not exist" {
|
||||
do! ThemeDataTests.``FindByIdWithoutText succeeds when the theme does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "Save" [
|
||||
testTask "succeeds when adding a theme" {
|
||||
do! ThemeDataTests.``Save succeeds when adding a theme`` data.Value
|
||||
}
|
||||
testTask "succeeds when updating a theme" {
|
||||
do! ThemeDataTests.``Save succeeds when updating a theme`` data.Value
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "succeeds when a theme is deleted" {
|
||||
do! ThemeDataTests.``Delete succeeds when a theme is deleted`` data.Value
|
||||
}
|
||||
testTask "succeeds when a theme is not deleted" {
|
||||
do! ThemeDataTests.``Delete succeeds when a theme is not deleted`` data.Value
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
let private themeAssetTests = testList "ThemeAsset" [
|
||||
testList "Save" [
|
||||
testTask "succeeds when adding an asset" {
|
||||
do! ThemeDataTests.Asset.``Save succeeds when adding an asset`` data.Value
|
||||
}
|
||||
testTask "succeeds when updating an asset" {
|
||||
do! ThemeDataTests.Asset.``Save succeeds when updating an asset`` data.Value
|
||||
}
|
||||
]
|
||||
testTask "All succeeds" {
|
||||
do! ThemeDataTests.Asset.``All succeeds`` data.Value
|
||||
}
|
||||
testList "FindById" [
|
||||
testTask "succeeds when an asset is found" {
|
||||
do! ThemeDataTests.Asset.``FindById succeeds when an asset is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when an asset is not found" {
|
||||
do! ThemeDataTests.Asset.``FindById succeeds when an asset is not found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindByTheme" [
|
||||
testTask "succeeds when assets exist" {
|
||||
do! ThemeDataTests.Asset.``FindByTheme succeeds when assets exist`` data.Value
|
||||
}
|
||||
testTask "succeeds when assets do not exist" {
|
||||
do! ThemeDataTests.Asset.``FindByTheme succeeds when assets do not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindByThemeWithData" [
|
||||
testTask "succeeds when assets exist" {
|
||||
do! ThemeDataTests.Asset.``FindByThemeWithData succeeds when assets exist`` data.Value
|
||||
}
|
||||
testTask "succeeds when assets do not exist" {
|
||||
do! ThemeDataTests.Asset.``FindByThemeWithData succeeds when assets do not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "DeleteByTheme" [
|
||||
testTask "succeeds when assets are deleted" {
|
||||
do! ThemeDataTests.Asset.``DeleteByTheme succeeds when assets are deleted`` data.Value
|
||||
}
|
||||
testTask "succeeds when no assets are deleted" {
|
||||
do! ThemeDataTests.Asset.``DeleteByTheme succeeds when no assets are deleted`` data.Value
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
let private uploadTests = testList "Upload" [
|
||||
testTask "Add succeeds" {
|
||||
do! UploadDataTests.``Add succeeds`` data.Value
|
||||
}
|
||||
testList "FindByPath" [
|
||||
testTask "succeeds when an upload is found" {
|
||||
do! UploadDataTests.``FindByPath succeeds when an upload is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when an upload is not found (incorrect weblog)" {
|
||||
do! UploadDataTests.``FindByPath succeeds when an upload is not found (incorrect weblog)`` data.Value
|
||||
}
|
||||
testTask "succeeds when an upload is not found (bad path)" {
|
||||
do! UploadDataTests.``FindByPath succeeds when an upload is not found (bad path)`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindByWebLog" [
|
||||
testTask "succeeds when uploads exist" {
|
||||
do! UploadDataTests.``FindByWebLog succeeds when uploads exist`` data.Value
|
||||
}
|
||||
testTask "succeeds when no uploads exist" {
|
||||
do! UploadDataTests.``FindByWebLog succeeds when no uploads exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindByWebLogWithData" [
|
||||
testTask "succeeds when uploads exist" {
|
||||
do! UploadDataTests.``FindByWebLogWithData succeeds when uploads exist`` data.Value
|
||||
}
|
||||
testTask "succeeds when no uploads exist" {
|
||||
do! UploadDataTests.``FindByWebLogWithData succeeds when no uploads exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "succeeds when an upload is deleted" {
|
||||
do! UploadDataTests.``Delete succeeds when an upload is deleted`` data.Value
|
||||
}
|
||||
testTask "succeeds when an upload is not deleted" {
|
||||
do! UploadDataTests.``Delete succeeds when an upload is not deleted`` data.Value
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
let private webLogUserTests = testList "WebLogUser" [
|
||||
testTask "Add succeeds" {
|
||||
// This restore ensures all the posts and pages exist
|
||||
do! freshEnvironment ()
|
||||
do! WebLogUserDataTests.``Add succeeds`` data.Value
|
||||
}
|
||||
testList "FindByEmail" [
|
||||
testTask "succeeds when a user is found" {
|
||||
do! WebLogUserDataTests.``FindByEmail succeeds when a user is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a user is not found (incorrect weblog)" {
|
||||
do! WebLogUserDataTests.``FindByEmail succeeds when a user is not found (incorrect weblog)`` data.Value
|
||||
}
|
||||
testTask "succeeds when a user is not found (bad email)" {
|
||||
do! WebLogUserDataTests.``FindByEmail succeeds when a user is not found (bad email)`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindById" [
|
||||
testTask "succeeds when a user is found" {
|
||||
do! WebLogUserDataTests.``FindById succeeds when a user is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a user is not found (incorrect weblog)" {
|
||||
do! WebLogUserDataTests.``FindById succeeds when a user is not found (incorrect weblog)`` data.Value
|
||||
}
|
||||
testTask "succeeds when a user is not found (bad ID)" {
|
||||
do! WebLogUserDataTests.``FindById succeeds when a user is not found (bad ID)`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindByWebLog" [
|
||||
testTask "succeeds when users exist" {
|
||||
do! WebLogUserDataTests.``FindByWebLog succeeds when users exist`` data.Value
|
||||
}
|
||||
testTask "succeeds when no users exist" {
|
||||
do! WebLogUserDataTests.``FindByWebLog succeeds when no users exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindNames" [
|
||||
testTask "succeeds when users exist" {
|
||||
do! WebLogUserDataTests.``FindNames succeeds when users exist`` data.Value
|
||||
}
|
||||
testTask "succeeds when users do not exist" {
|
||||
do! WebLogUserDataTests.``FindNames succeeds when users do not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "SetLastSeen" [
|
||||
testTask "succeeds when the user exists" {
|
||||
do! WebLogUserDataTests.``SetLastSeen succeeds when the user exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the user does not exist" {
|
||||
do! WebLogUserDataTests.``SetLastSeen succeeds when the user does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "Update" [
|
||||
testTask "succeeds when the user exists" {
|
||||
do! WebLogUserDataTests.``Update succeeds when the user exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the user does not exist" {
|
||||
do! WebLogUserDataTests.``Update succeeds when the user does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "fails when the user is the author of a page" {
|
||||
do! WebLogUserDataTests.``Delete fails when the user is the author of a page`` data.Value
|
||||
}
|
||||
testTask "fails when the user is the author of a post" {
|
||||
do! WebLogUserDataTests.``Delete fails when the user is the author of a post`` data.Value
|
||||
}
|
||||
testTask "succeeds when the user is not an author" {
|
||||
do! WebLogUserDataTests.``Delete succeeds when the user is not an author`` data.Value
|
||||
}
|
||||
testTask "succeeds when the user does not exist" {
|
||||
do! WebLogUserDataTests.``Delete succeeds when the user does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
let private webLogTests = testList "WebLog" [
|
||||
testTask "Add succeeds" {
|
||||
do! WebLogDataTests.``Add succeeds`` data.Value
|
||||
}
|
||||
testTask "All succeeds" {
|
||||
do! WebLogDataTests.``All succeeds`` data.Value
|
||||
}
|
||||
testList "FindByHost" [
|
||||
testTask "succeeds when a web log is found" {
|
||||
do! WebLogDataTests.``FindByHost succeeds when a web log is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a web log is not found" {
|
||||
do! WebLogDataTests.``FindByHost succeeds when a web log is not found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "FindById" [
|
||||
testTask "succeeds when a web log is found" {
|
||||
do! WebLogDataTests.``FindById succeeds when a web log is found`` data.Value
|
||||
}
|
||||
testTask "succeeds when a web log is not found" {
|
||||
do! WebLogDataTests.``FindById succeeds when a web log is not found`` data.Value
|
||||
}
|
||||
]
|
||||
testList "UpdateRedirectRules" [
|
||||
testTask "succeeds when the web log exists" {
|
||||
do! WebLogDataTests.``UpdateRedirectRules succeeds when the web log exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the web log does not exist" {
|
||||
do! WebLogDataTests.``UpdateRedirectRules succeeds when the web log does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "UpdateRssOptions" [
|
||||
testTask "succeeds when the web log exists" {
|
||||
do! WebLogDataTests.``UpdateRssOptions succeeds when the web log exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the web log does not exist" {
|
||||
do! WebLogDataTests.``UpdateRssOptions succeeds when the web log does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "UpdateSettings" [
|
||||
testTask "succeeds when the web log exists" {
|
||||
do! WebLogDataTests.``UpdateSettings succeeds when the web log exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the web log does not exist" {
|
||||
do! WebLogDataTests.``UpdateSettings succeeds when the web log does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
testList "Delete" [
|
||||
testTask "succeeds when the web log exists" {
|
||||
do! WebLogDataTests.``Delete succeeds when the web log exists`` data.Value
|
||||
}
|
||||
testTask "succeeds when the web log does not exist" {
|
||||
do! WebLogDataTests.``Delete succeeds when the web log does not exist`` data.Value
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Drop the throwaway RethinkDB database
|
||||
let private environmentCleanUp = testTask "Clean Up" {
|
||||
do! disposeData ()
|
||||
}
|
||||
|
||||
/// All RethinkDB data tests
|
||||
let all =
|
||||
testList "RethinkDbData"
|
||||
[ environmentSetUp
|
||||
categoryTests
|
||||
pageTests
|
||||
postTests
|
||||
tagMapTests
|
||||
themeTests
|
||||
themeAssetTests
|
||||
uploadTests
|
||||
webLogUserTests
|
||||
webLogTests
|
||||
environmentCleanUp ]
|
||||
|> testSequenced
|
||||
1054
src/MyWebLog.Tests/Data/SQLiteDataTests.fs
Normal file
1054
src/MyWebLog.Tests/Data/SQLiteDataTests.fs
Normal file
File diff suppressed because it is too large
Load Diff
112
src/MyWebLog.Tests/Data/TagMapDataTests.fs
Normal file
112
src/MyWebLog.Tests/Data/TagMapDataTests.fs
Normal file
@@ -0,0 +1,112 @@
|
||||
/// <summary>
|
||||
/// Integration tests for <see cref="ITagMapData" /> implementations
|
||||
/// </summary>
|
||||
module TagMapDataTests
|
||||
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open MyWebLog.Data
|
||||
|
||||
/// The ID of the root web log
|
||||
let private rootId = CategoryDataTests.rootId
|
||||
|
||||
/// The ID of the f# tag
|
||||
let private fSharpId = TagMapId "Icm027noqE-rPHKZA98vAw"
|
||||
|
||||
/// The ID of the ghoti tag
|
||||
let private fishId = TagMapId "GdryXh-S0kGsNBs2RIacGA"
|
||||
|
||||
let ``FindById succeeds when a tag mapping is found`` (data: IData) = task {
|
||||
let! tagMap = data.TagMap.FindById fSharpId rootId
|
||||
Expect.isSome tagMap "There should have been a tag mapping returned"
|
||||
let tag = tagMap.Value
|
||||
Expect.equal tag.Id fSharpId "ID is incorrect"
|
||||
Expect.equal tag.WebLogId rootId "Web log ID is incorrect"
|
||||
Expect.equal tag.Tag "f#" "Tag is incorrect"
|
||||
Expect.equal tag.UrlValue "f-sharp" "URL value is incorrect"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a tag mapping is not found (incorrect weblog)`` (data: IData) = task {
|
||||
let! tagMap = data.TagMap.FindById fSharpId (WebLogId "wrong")
|
||||
Expect.isNone tagMap "There should not have been a tag mapping returned"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a tag mapping is not found (bad tag map ID)`` (data: IData) = task {
|
||||
let! tagMap = data.TagMap.FindById (TagMapId "out") rootId
|
||||
Expect.isNone tagMap "There should not have been a tag mapping returned"
|
||||
}
|
||||
|
||||
let ``FindByUrlValue succeeds when a tag mapping is found`` (data: IData) = task {
|
||||
let! tagMap = data.TagMap.FindByUrlValue "f-sharp" rootId
|
||||
Expect.isSome tagMap "There should have been a tag mapping returned"
|
||||
Expect.equal tagMap.Value.Id fSharpId "ID is incorrect"
|
||||
}
|
||||
|
||||
let ``FindByUrlValue succeeds when a tag mapping is not found (incorrect weblog)`` (data: IData) = task {
|
||||
let! tagMap = data.TagMap.FindByUrlValue "f-sharp" (WebLogId "incorrect")
|
||||
Expect.isNone tagMap "There should not have been a tag mapping returned"
|
||||
}
|
||||
|
||||
let ``FindByUrlValue succeeds when a tag mapping is not found (no such value)`` (data: IData) = task {
|
||||
let! tagMap = data.TagMap.FindByUrlValue "c-sharp" rootId
|
||||
Expect.isNone tagMap "There should not have been a tag mapping returned"
|
||||
}
|
||||
|
||||
let ``FindByWebLog succeeds when tag mappings are found`` (data: IData) = task {
|
||||
let! mappings = data.TagMap.FindByWebLog rootId
|
||||
Expect.hasLength mappings 2 "There should have been 2 tag mappings returned"
|
||||
for mapping in mappings do
|
||||
Expect.contains [ fSharpId; fishId ] mapping.Id $"Unexpected mapping ID ({mapping.Id})"
|
||||
Expect.equal mapping.WebLogId rootId "Web log ID is incorrect"
|
||||
Expect.isNotEmpty mapping.Tag "Tag should not have been blank"
|
||||
Expect.isNotEmpty mapping.UrlValue "URL value should not have been blank"
|
||||
}
|
||||
|
||||
let ``FindByWebLog succeeds when no tag mappings are found`` (data: IData) = task {
|
||||
let! mappings = data.TagMap.FindByWebLog (WebLogId "no-maps")
|
||||
Expect.isEmpty mappings "There should have been no tag mappings returned"
|
||||
}
|
||||
|
||||
let ``FindMappingForTags succeeds when mappings exist`` (data: IData) = task {
|
||||
let! mappings = data.TagMap.FindMappingForTags [ "f#"; "testing"; "unit" ] rootId
|
||||
Expect.hasLength mappings 1 "There should have been one mapping returned"
|
||||
Expect.equal mappings[0].Id fSharpId "The wrong mapping was returned"
|
||||
}
|
||||
|
||||
let ``FindMappingForTags succeeds when no mappings exist`` (data: IData) = task {
|
||||
let! mappings = data.TagMap.FindMappingForTags [ "c#"; "turkey"; "ham" ] rootId
|
||||
Expect.isEmpty mappings "There should have been no tag mappings returned"
|
||||
}
|
||||
|
||||
let ``Save succeeds when adding a tag mapping`` (data: IData) = task {
|
||||
let mapId = TagMapId "test"
|
||||
do! data.TagMap.Save { Id = mapId; WebLogId = rootId; Tag = "c#"; UrlValue = "c-sharp" }
|
||||
let! mapping = data.TagMap.FindById mapId rootId
|
||||
Expect.isSome mapping "The mapping should have been retrieved"
|
||||
let tag = mapping.Value
|
||||
Expect.equal tag.Id mapId "ID is incorrect"
|
||||
Expect.equal tag.WebLogId rootId "Web log ID is incorrect"
|
||||
Expect.equal tag.Tag "c#" "Tag is incorrect"
|
||||
Expect.equal tag.UrlValue "c-sharp" "URL value is incorrect"
|
||||
}
|
||||
|
||||
let ``Save succeeds when updating a tag mapping`` (data: IData) = task {
|
||||
do! data.TagMap.Save { Id = fishId; WebLogId = rootId; Tag = "halibut"; UrlValue = "mackerel" }
|
||||
let! mapping = data.TagMap.FindById fishId rootId
|
||||
Expect.isSome mapping "The mapping should have been retrieved"
|
||||
let tag = mapping.Value
|
||||
Expect.equal tag.Id fishId "ID is incorrect"
|
||||
Expect.equal tag.WebLogId rootId "Web log ID is incorrect"
|
||||
Expect.equal tag.Tag "halibut" "Tag is incorrect"
|
||||
Expect.equal tag.UrlValue "mackerel" "URL value is incorrect"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when a tag mapping is deleted`` (data: IData) = task {
|
||||
let! deleted = data.TagMap.Delete fSharpId rootId
|
||||
Expect.isTrue deleted "The tag mapping should have been deleted"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when a tag mapping is not deleted`` (data: IData) = task {
|
||||
let! deleted = data.TagMap.Delete fSharpId rootId // this was deleted above
|
||||
Expect.isFalse deleted "A tag mapping should not have been deleted"
|
||||
}
|
||||
234
src/MyWebLog.Tests/Data/ThemeDataTests.fs
Normal file
234
src/MyWebLog.Tests/Data/ThemeDataTests.fs
Normal file
@@ -0,0 +1,234 @@
|
||||
/// <summary>
|
||||
/// Integration tests for <see cref="IThemeData" /> implementations
|
||||
/// </summary>
|
||||
module ThemeDataTests
|
||||
|
||||
open System.IO
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open MyWebLog.Data
|
||||
open NodaTime
|
||||
|
||||
/// The ID of the default theme (restored from root-weblog.json)
|
||||
let private defaultId = ThemeId "default"
|
||||
|
||||
/// The ID of the test theme loaded and manipulated by these tests
|
||||
let private testId = ThemeId "test-theme"
|
||||
|
||||
/// The dark version of the myWebLog logo
|
||||
let private darkFile = File.ReadAllBytes "../admin-theme/wwwroot/logo-dark.png"
|
||||
|
||||
/// The light version of the myWebLog logo
|
||||
let private lightFile = File.ReadAllBytes "../admin-theme/wwwroot/logo-light.png"
|
||||
|
||||
/// Ensure that theme templates do not have any text
|
||||
let private ensureNoText theme =
|
||||
for template in theme.Templates do
|
||||
Expect.equal template.Text "" $"Text for template {template.Name} should have been blank"
|
||||
|
||||
let ``All succeeds`` (data: IData) = task {
|
||||
let! themes = data.Theme.All()
|
||||
Expect.hasLength themes 1 "There should have been one theme returned"
|
||||
Expect.equal themes[0].Id defaultId "ID was incorrect"
|
||||
Expect.equal themes[0].Name "myWebLog Default Theme" "Name was incorrect"
|
||||
Expect.equal themes[0].Version "2.1.0" "Version was incorrect"
|
||||
ensureNoText themes[0]
|
||||
}
|
||||
|
||||
let ``Exists succeeds when the theme exists`` (data: IData) = task {
|
||||
let! exists = data.Theme.Exists defaultId
|
||||
Expect.isTrue exists "The \"default\" theme should have existed"
|
||||
}
|
||||
|
||||
let ``Exists succeeds when the theme does not exist`` (data: IData) = task {
|
||||
let! exists = data.Theme.Exists (ThemeId "fancy")
|
||||
Expect.isFalse exists "The \"fancy\" theme should not have existed"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when the theme exists`` (data: IData) = task {
|
||||
let! theme = data.Theme.FindById defaultId
|
||||
Expect.isSome theme "The theme should have been found"
|
||||
let it = theme.Value
|
||||
Expect.equal it.Id defaultId "ID was incorrect"
|
||||
Expect.equal it.Name "myWebLog Default Theme" "Name was incorrect"
|
||||
Expect.equal it.Version "2.1.0" "Version was incorrect"
|
||||
for template in it.Templates do
|
||||
Expect.isNotEmpty template.Text $"Text for template {template.Name} should not have been blank"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when the theme does not exist`` (data: IData) = task {
|
||||
let! theme = data.Theme.FindById (ThemeId "missing")
|
||||
Expect.isNone theme "There should not have been a theme found"
|
||||
}
|
||||
|
||||
let ``FindByIdWithoutText succeeds when the theme exists`` (data: IData) = task {
|
||||
let! theme = data.Theme.FindByIdWithoutText defaultId
|
||||
Expect.isSome theme "The theme should have been found"
|
||||
let it = theme.Value
|
||||
Expect.equal it.Id defaultId "ID was incorrect"
|
||||
ensureNoText it
|
||||
}
|
||||
|
||||
let ``FindByIdWithoutText succeeds when the theme does not exist`` (data: IData) = task {
|
||||
let! theme = data.Theme.FindByIdWithoutText (ThemeId "ornate")
|
||||
Expect.isNone theme "There should not have been a theme found"
|
||||
}
|
||||
|
||||
let ``Save succeeds when adding a theme`` (data: IData) = task {
|
||||
do! data.Theme.Save
|
||||
{ Id = testId
|
||||
Name = "Test Theme"
|
||||
Version = "evergreen"
|
||||
Templates =
|
||||
[ { Name = "index"; Text = "<h1>{{ values_here }}</h1>" }
|
||||
{ Name = "single-post"; Text = "<p>{{ the_post }}" } ] }
|
||||
let! saved = data.Theme.FindById testId
|
||||
Expect.isSome saved "There should have been a theme returned"
|
||||
let it = saved.Value
|
||||
Expect.equal it.Id testId "ID was incorrect"
|
||||
Expect.equal it.Name "Test Theme" "Name was incorrect"
|
||||
Expect.equal it.Version "evergreen" "Version was incorrect"
|
||||
Expect.hasLength it.Templates 2 "There should have been 2 templates"
|
||||
Expect.equal it.Templates[0].Name "index" "Template 0 name incorrect"
|
||||
Expect.equal it.Templates[0].Text "<h1>{{ values_here }}</h1>" "Template 0 text incorrect"
|
||||
Expect.equal it.Templates[1].Name "single-post" "Template 1 name incorrect"
|
||||
Expect.equal it.Templates[1].Text "<p>{{ the_post }}" "Template 1 text incorrect"
|
||||
}
|
||||
|
||||
let ``Save succeeds when updating a theme`` (data: IData) = task {
|
||||
do! data.Theme.Save
|
||||
{ Id = testId
|
||||
Name = "Updated Theme"
|
||||
Version = "still evergreen"
|
||||
Templates =
|
||||
[ { Name = "index"; Text = "<h1>{{ values_there }}</h1>" }
|
||||
{ Name = "layout"; Text = "<!DOCTYPE html><etc />" }
|
||||
{ Name = "single-post"; Text = "<p>{{ the_post }}" } ] }
|
||||
let! updated = data.Theme.FindById testId
|
||||
Expect.isSome updated "The updated theme should have been returned"
|
||||
let it = updated.Value
|
||||
Expect.equal it.Id testId "ID was incorrect"
|
||||
Expect.equal it.Name "Updated Theme" "Name was incorrect"
|
||||
Expect.equal it.Version "still evergreen" "Version was incorrect"
|
||||
Expect.hasLength it.Templates 3 "There should have been 3 templates"
|
||||
Expect.equal it.Templates[0].Name "index" "Template 0 name incorrect"
|
||||
Expect.equal it.Templates[0].Text "<h1>{{ values_there }}</h1>" "Template 0 text incorrect"
|
||||
Expect.equal it.Templates[1].Name "layout" "Template 1 name incorrect"
|
||||
Expect.equal it.Templates[1].Text "<!DOCTYPE html><etc />" "Template 1 text incorrect"
|
||||
Expect.equal it.Templates[2].Name "single-post" "Template 2 name incorrect"
|
||||
Expect.equal it.Templates[2].Text "<p>{{ the_post }}" "Template 2 text incorrect"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when a theme is deleted`` (data: IData) = task {
|
||||
// Delete should also delete assets associated with the theme
|
||||
do! data.ThemeAsset.Save { Id = ThemeAssetId (testId, "logo-dark.png"); UpdatedOn = Noda.epoch; Data = darkFile }
|
||||
do! data.ThemeAsset.Save { Id = ThemeAssetId (testId, "logo-light.png"); UpdatedOn = Noda.epoch; Data = lightFile }
|
||||
let! deleted = data.Theme.Delete testId
|
||||
Expect.isTrue deleted "The theme should have been deleted"
|
||||
let! assets = data.ThemeAsset.FindByTheme testId
|
||||
Expect.isEmpty assets "The theme's assets should have been deleted"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when a theme is not deleted`` (data: IData) = task {
|
||||
let! deleted = data.Theme.Delete (ThemeId "test-theme") // already deleted above
|
||||
Expect.isFalse deleted "The theme should not have been deleted"
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Integration tests for <see cref="IThemeAssetData" /> implementations
|
||||
/// </summary>
|
||||
module Asset =
|
||||
|
||||
/// The theme ID for which assets will be tested
|
||||
let private assetThemeId = ThemeId "asset-test"
|
||||
|
||||
/// The asset ID for the dark logo
|
||||
let private darkId = ThemeAssetId (assetThemeId, "logo-dark.png")
|
||||
|
||||
/// The asset ID for the light logo
|
||||
let private lightId = ThemeAssetId (assetThemeId, "logo-light.png")
|
||||
|
||||
let ``Save succeeds when adding an asset`` (data: IData) = task {
|
||||
do! data.Theme.Save { Theme.Empty with Id = assetThemeId }
|
||||
do! data.ThemeAsset.Save { Id = lightId; UpdatedOn = Noda.epoch + Duration.FromDays 18; Data = lightFile }
|
||||
let! asset = data.ThemeAsset.FindById lightId
|
||||
Expect.isSome asset "The asset should have been found"
|
||||
let it = asset.Value
|
||||
Expect.equal it.Id lightId "ID was incorrect"
|
||||
Expect.equal it.UpdatedOn (Noda.epoch + Duration.FromDays 18) "Updated on was incorrect"
|
||||
Expect.equal it.Data lightFile "Data was incorrect"
|
||||
}
|
||||
|
||||
let ``Save succeeds when updating an asset`` (data: IData) = task {
|
||||
do! data.ThemeAsset.Save { Id = lightId; UpdatedOn = Noda.epoch + Duration.FromDays 20; Data = darkFile }
|
||||
let! asset = data.ThemeAsset.FindById lightId
|
||||
Expect.isSome asset "The asset should have been found"
|
||||
let it = asset.Value
|
||||
Expect.equal it.Id lightId "ID was incorrect"
|
||||
Expect.equal it.UpdatedOn (Noda.epoch + Duration.FromDays 20) "Updated on was incorrect"
|
||||
Expect.equal it.Data darkFile "Data was incorrect"
|
||||
}
|
||||
|
||||
let ``All succeeds`` (data: IData) = task {
|
||||
let! all = data.ThemeAsset.All()
|
||||
Expect.hasLength all 2 "There should have been 2 assets retrieved"
|
||||
for asset in all do
|
||||
Expect.contains
|
||||
[ ThemeAssetId (defaultId, "style.css"); lightId ] asset.Id $"Unexpected asset found ({asset.Id})"
|
||||
Expect.isEmpty asset.Data $"Asset {asset.Id} should not have had data"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when an asset is found`` (data: IData) = task {
|
||||
let! asset = data.ThemeAsset.FindById lightId
|
||||
Expect.isSome asset "The asset should have been found"
|
||||
let it = asset.Value
|
||||
Expect.equal it.Id lightId "ID was incorrect"
|
||||
Expect.equal it.UpdatedOn (Noda.epoch + Duration.FromDays 20) "Updated on was incorrect"
|
||||
Expect.equal it.Data darkFile "Data was incorrect"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when an asset is not found`` (data: IData) = task {
|
||||
let! asset = data.ThemeAsset.FindById (ThemeAssetId (assetThemeId, "404.jpg"))
|
||||
Expect.isNone asset "There should not have been an asset returned"
|
||||
}
|
||||
|
||||
let ``FindByTheme succeeds when assets exist`` (data: IData) = task {
|
||||
do! data.ThemeAsset.Save { Id = darkId; UpdatedOn = Noda.epoch; Data = darkFile }
|
||||
do! data.ThemeAsset.Save { Id = lightId; UpdatedOn = Noda.epoch; Data = lightFile }
|
||||
let! assets = data.ThemeAsset.FindByTheme assetThemeId
|
||||
Expect.hasLength assets 2 "There should have been 2 assets returned"
|
||||
for asset in assets do
|
||||
Expect.contains [ darkId; lightId ] asset.Id $"Unexpected asset found ({asset.Id})"
|
||||
Expect.equal asset.UpdatedOn Noda.epoch $"Updated on was incorrect ({asset.Id})"
|
||||
Expect.isEmpty asset.Data $"Data should not have been retrieved ({asset.Id})"
|
||||
}
|
||||
|
||||
let ``FindByTheme succeeds when assets do not exist`` (data: IData) = task {
|
||||
let! assets = data.ThemeAsset.FindByTheme (ThemeId "no-assets-here")
|
||||
Expect.isEmpty assets "There should have been no assets returned"
|
||||
}
|
||||
|
||||
let ``FindByThemeWithData succeeds when assets exist`` (data: IData) = task {
|
||||
let! assets = data.ThemeAsset.FindByThemeWithData assetThemeId
|
||||
Expect.hasLength assets 2 "There should have been 2 assets returned"
|
||||
let darkLogo = assets |> List.find (fun it -> it.Id = darkId)
|
||||
Expect.equal darkLogo.Data darkFile "The dark asset's data is incorrect"
|
||||
let lightLogo = assets |> List.find (fun it -> it.Id = lightId)
|
||||
Expect.equal lightLogo.Data lightFile "The light asset's data is incorrect"
|
||||
}
|
||||
|
||||
let ``FindByThemeWithData succeeds when assets do not exist`` (data: IData) = task {
|
||||
let! assets = data.ThemeAsset.FindByThemeWithData (ThemeId "still-no-assets")
|
||||
Expect.isEmpty assets "There should have been no assets returned"
|
||||
}
|
||||
|
||||
let ``DeleteByTheme succeeds when assets are deleted`` (data: IData) = task {
|
||||
do! data.ThemeAsset.DeleteByTheme assetThemeId
|
||||
let! assets = data.ThemeAsset.FindByTheme assetThemeId
|
||||
Expect.isEmpty assets "There should be no assets remaining"
|
||||
}
|
||||
|
||||
let ``DeleteByTheme succeeds when no assets are deleted`` (data: IData) = task {
|
||||
do! data.ThemeAsset.DeleteByTheme assetThemeId // already deleted above
|
||||
Expect.isTrue true "The above did not raise an exception; that's the test"
|
||||
}
|
||||
95
src/MyWebLog.Tests/Data/UploadDataTests.fs
Normal file
95
src/MyWebLog.Tests/Data/UploadDataTests.fs
Normal file
@@ -0,0 +1,95 @@
|
||||
/// <summary>
|
||||
/// Integration tests for <see cref="IUploadData" /> implementations
|
||||
/// </summary>
|
||||
module UploadDataTests
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open MyWebLog.Data
|
||||
open NodaTime
|
||||
|
||||
/// The ID of the root web log
|
||||
let private rootId = CategoryDataTests.rootId
|
||||
|
||||
/// The ID of the favicon upload
|
||||
let private faviconId = UploadId "XweKbWQiOkqqrjEdgP9wwg"
|
||||
|
||||
let ``Add succeeds`` (data: IData) = task {
|
||||
let file = File.ReadAllBytes "../admin-theme/wwwroot/logo-dark.png"
|
||||
do! data.Upload.Add
|
||||
{ Id = UploadId "new-upload"
|
||||
WebLogId = rootId
|
||||
UpdatedOn = Noda.epoch + Duration.FromDays 30
|
||||
Path = Permalink "1970/01/logo-dark.png"
|
||||
Data = file }
|
||||
let! added = data.Upload.FindByPath "1970/01/logo-dark.png" rootId
|
||||
Expect.isSome added "There should have been an upload returned"
|
||||
let upload = added.Value
|
||||
Expect.equal upload.Id (UploadId "new-upload") "ID is incorrect"
|
||||
Expect.equal upload.WebLogId rootId "Web log ID is incorrect"
|
||||
Expect.equal upload.UpdatedOn (Noda.epoch + Duration.FromDays 30) "Updated on is incorrect"
|
||||
Expect.equal upload.Path (Permalink "1970/01/logo-dark.png") "Path is incorrect"
|
||||
Expect.equal upload.Data file "Data is incorrect"
|
||||
}
|
||||
|
||||
let ``FindByPath succeeds when an upload is found`` (data: IData) = task {
|
||||
let! upload = data.Upload.FindByPath "2022/06/favicon.ico" rootId
|
||||
Expect.isSome upload "There should have been an upload returned"
|
||||
let it = upload.Value
|
||||
Expect.equal it.Id faviconId "ID is incorrect"
|
||||
Expect.equal it.WebLogId rootId "Web log ID is incorrect"
|
||||
Expect.equal
|
||||
it.UpdatedOn (Instant.FromDateTimeOffset(DateTimeOffset.Parse "2022-06-23T21:15:40Z")) "Updated on is incorrect"
|
||||
Expect.equal it.Path (Permalink "2022/06/favicon.ico") "Path is incorrect"
|
||||
Expect.isNonEmpty it.Data "Data should have been retrieved"
|
||||
}
|
||||
|
||||
let ``FindByPath succeeds when an upload is not found (incorrect weblog)`` (data: IData) = task {
|
||||
let! upload = data.Upload.FindByPath "2022/06/favicon.ico" (WebLogId "wrong")
|
||||
Expect.isNone upload "There should not have been an upload returned"
|
||||
}
|
||||
|
||||
let ``FindByPath succeeds when an upload is not found (bad path)`` (data: IData) = task {
|
||||
let! upload = data.Upload.FindByPath "2022/07/favicon.ico" rootId
|
||||
Expect.isNone upload "There should not have been an upload returned"
|
||||
}
|
||||
|
||||
let ``FindByWebLog succeeds when uploads exist`` (data: IData) = task {
|
||||
let! uploads = data.Upload.FindByWebLog rootId
|
||||
Expect.hasLength uploads 2 "There should have been 2 uploads returned"
|
||||
for upload in uploads do
|
||||
Expect.contains [ faviconId; UploadId "new-upload" ] upload.Id $"Unexpected upload returned ({upload.Id})"
|
||||
Expect.isEmpty upload.Data $"Upload should not have had its data ({upload.Id})"
|
||||
}
|
||||
|
||||
let ``FindByWebLog succeeds when no uploads exist`` (data: IData) = task {
|
||||
let! uploads = data.Upload.FindByWebLog (WebLogId "nothing")
|
||||
Expect.isEmpty uploads "There should have been no uploads returned"
|
||||
}
|
||||
|
||||
let ``FindByWebLogWithData succeeds when uploads exist`` (data: IData) = task {
|
||||
let! uploads = data.Upload.FindByWebLogWithData rootId
|
||||
Expect.hasLength uploads 2 "There should have been 2 uploads returned"
|
||||
for upload in uploads do
|
||||
Expect.contains [ faviconId; UploadId "new-upload" ] upload.Id $"Unexpected upload returned ({upload.Id})"
|
||||
Expect.isNonEmpty upload.Data $"Upload should have had its data ({upload.Id})"
|
||||
}
|
||||
|
||||
let ``FindByWebLogWithData succeeds when no uploads exist`` (data: IData) = task {
|
||||
let! uploads = data.Upload.FindByWebLogWithData (WebLogId "data-nope")
|
||||
Expect.isEmpty uploads "There should have been no uploads returned"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when an upload is deleted`` (data: IData) = task {
|
||||
match! data.Upload.Delete faviconId rootId with
|
||||
| Ok path -> Expect.equal path "2022/06/favicon.ico" "The path of the deleted upload was incorrect"
|
||||
| Error it -> Expect.isTrue false $"Upload deletion should have succeeded (message {it})"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when an upload is not deleted`` (data: IData) = task {
|
||||
match! data.Upload.Delete faviconId rootId with
|
||||
| Ok it -> Expect.isTrue false $"Upload deletion should not have succeeded (path {it})"
|
||||
| Error msg -> Expect.equal msg $"Upload ID {faviconId} not found" "Error message was incorrect"
|
||||
}
|
||||
96
src/MyWebLog.Tests/Data/UtilsTests.fs
Normal file
96
src/MyWebLog.Tests/Data/UtilsTests.fs
Normal file
@@ -0,0 +1,96 @@
|
||||
module UtilsTests
|
||||
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open MyWebLog.Data
|
||||
open NodaTime
|
||||
|
||||
/// Unit tests for the orderByHierarchy function
|
||||
let orderByHierarchyTests = test "orderByHierarchy succeeds" {
|
||||
let rawCats =
|
||||
[ { Category.Empty with Id = CategoryId "a"; Name = "Audio"; Slug = "audio"; ParentId = Some (CategoryId "p") }
|
||||
{ Category.Empty with
|
||||
Id = CategoryId "b"
|
||||
Name = "Breaking"
|
||||
Description = Some "Breaking News"
|
||||
Slug = "breaking"
|
||||
ParentId = Some (CategoryId "n") }
|
||||
{ Category.Empty with Id = CategoryId "l"; Name = "Local"; Slug = "local"; ParentId = Some (CategoryId "b") }
|
||||
{ Category.Empty with Id = CategoryId "n"; Name = "News"; Slug = "news" }
|
||||
{ Category.Empty with Id = CategoryId "p"; Name = "Podcast"; Slug = "podcast" }
|
||||
{ Category.Empty with Id = CategoryId "v"; Name = "Video"; Slug = "vid"; ParentId = Some (CategoryId "p") } ]
|
||||
let cats = Utils.orderByHierarchy rawCats None None [] |> List.ofSeq
|
||||
Expect.equal cats.Length 6 "There should have been 6 categories"
|
||||
Expect.equal cats[0].Id "n" "The first top-level category should have been News"
|
||||
Expect.equal cats[0].Slug "news" "Slug for News not filled properly"
|
||||
Expect.isEmpty cats[0].ParentNames "Parent names for News not filled properly"
|
||||
Expect.equal cats[1].Id "b" "Breaking should have been just below News"
|
||||
Expect.equal cats[1].Slug "news/breaking" "Slug for Breaking not filled properly"
|
||||
Expect.equal cats[1].Name "Breaking" "Name not filled properly"
|
||||
Expect.equal cats[1].Description (Some "Breaking News") "Description not filled properly"
|
||||
Expect.equal cats[1].ParentNames [| "News" |] "Parent names for Breaking not filled properly"
|
||||
Expect.equal cats[2].Id "l" "Local should have been just below Breaking"
|
||||
Expect.equal cats[2].Slug "news/breaking/local" "Slug for Local not filled properly"
|
||||
Expect.equal cats[2].ParentNames [| "News"; "Breaking" |] "Parent names for Local not filled properly"
|
||||
Expect.equal cats[3].Id "p" "Podcast should have been the next top-level category"
|
||||
Expect.equal cats[3].Slug "podcast" "Slug for Podcast not filled properly"
|
||||
Expect.isEmpty cats[3].ParentNames "Parent names for Podcast not filled properly"
|
||||
Expect.equal cats[4].Id "a" "Audio should have been just below Podcast"
|
||||
Expect.equal cats[4].Slug "podcast/audio" "Slug for Audio not filled properly"
|
||||
Expect.equal cats[4].ParentNames [| "Podcast" |] "Parent names for Audio not filled properly"
|
||||
Expect.equal cats[5].Id "v" "Video should have been below Audio"
|
||||
Expect.equal cats[5].Slug "podcast/vid" "Slug for Video not filled properly"
|
||||
Expect.equal cats[5].ParentNames [| "Podcast" |] "Parent names for Video not filled properly"
|
||||
Expect.hasCountOf cats 6u (fun it -> it.PostCount = 0) "All post counts should have been 0"
|
||||
}
|
||||
|
||||
/// Unit tests for the diffLists function
|
||||
let diffListsTests = testList "diffLists" [
|
||||
test "succeeds with identical lists" {
|
||||
let removed, added = Utils.diffLists [ 1; 2; 3 ] [ 1; 2; 3 ] id
|
||||
Expect.isEmpty removed "There should have been no removed items returned"
|
||||
Expect.isEmpty added "There should have been no added items returned"
|
||||
}
|
||||
test "succeeds with differing lists" {
|
||||
let removed, added = Utils.diffLists [ 1; 2; 3 ] [ 3; 4; 5 ] string
|
||||
Expect.equal removed [ 1; 2 ] "Removed items incorrect"
|
||||
Expect.equal added [ 4; 5 ] "Added items incorrect"
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the diffRevisions function
|
||||
let diffRevisionsTests = testList "diffRevisions" [
|
||||
test "succeeds with identical lists" {
|
||||
let oldItems =
|
||||
[ { AsOf = Noda.epoch + Duration.FromDays 3; Text = Html "<p>test" }
|
||||
{ AsOf = Noda.epoch; Text = Html "<p>test test" } ]
|
||||
let newItems =
|
||||
[ { AsOf = Noda.epoch; Text = Html "<p>test test" }
|
||||
{ AsOf = Noda.epoch + Duration.FromDays 3; Text = Html "<p>test" } ]
|
||||
let removed, added = Utils.diffRevisions oldItems newItems
|
||||
Expect.isEmpty removed "There should have been no removed items returned"
|
||||
Expect.isEmpty added "There should have been no added items returned"
|
||||
}
|
||||
test "succeeds with differing lists" {
|
||||
let oldItems =
|
||||
[ { AsOf = Noda.epoch + Duration.FromDays 3; Text = Html "<p>test" }
|
||||
{ AsOf = Noda.epoch + Duration.FromDays 2; Text = Html "<p>tests" }
|
||||
{ AsOf = Noda.epoch; Text = Html "<p>test test" } ]
|
||||
let newItems =
|
||||
[ { AsOf = Noda.epoch + Duration.FromDays 4; Text = Html "<p>tests" }
|
||||
{ AsOf = Noda.epoch + Duration.FromDays 3; Text = Html "<p>test" }
|
||||
{ AsOf = Noda.epoch; Text = Html "<p>test test" } ]
|
||||
let removed, added = Utils.diffRevisions oldItems newItems
|
||||
Expect.equal removed.Length 1 "There should be 1 removed item"
|
||||
Expect.equal removed[0].AsOf (Noda.epoch + Duration.FromDays 2) "Expected removed item incorrect"
|
||||
Expect.equal added.Length 1 "There should be 1 added item"
|
||||
Expect.equal added[0].AsOf (Noda.epoch + Duration.FromDays 4) "Expected added item incorrect"
|
||||
}
|
||||
]
|
||||
|
||||
/// All tests for the Utils file
|
||||
let all = testList "Utils" [
|
||||
orderByHierarchyTests
|
||||
diffListsTests
|
||||
diffRevisionsTests
|
||||
]
|
||||
198
src/MyWebLog.Tests/Data/WebLogDataTests.fs
Normal file
198
src/MyWebLog.Tests/Data/WebLogDataTests.fs
Normal file
@@ -0,0 +1,198 @@
|
||||
/// <summary>
|
||||
/// Integration tests for <see cref="IWebLogData" /> implementations
|
||||
/// </summary>
|
||||
module WebLogDataTests
|
||||
|
||||
open System
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open MyWebLog.Data
|
||||
|
||||
/// The ID of the root web log
|
||||
let private rootId = CategoryDataTests.rootId
|
||||
|
||||
let ``Add succeeds`` (data: IData) = task {
|
||||
do! data.WebLog.Add
|
||||
{ Id = WebLogId "new-weblog"
|
||||
Name = "Test Web Log"
|
||||
Slug = "test-web-log"
|
||||
Subtitle = None
|
||||
DefaultPage = ""
|
||||
PostsPerPage = 7
|
||||
ThemeId = ThemeId "default"
|
||||
UrlBase = "https://example.com/new"
|
||||
TimeZone = "America/Los_Angeles"
|
||||
Rss =
|
||||
{ IsFeedEnabled = true
|
||||
FeedName = "my-feed.xml"
|
||||
ItemsInFeed = None
|
||||
IsCategoryEnabled = false
|
||||
IsTagEnabled = false
|
||||
Copyright = Some "go for it"
|
||||
CustomFeeds = [] }
|
||||
AutoHtmx = true
|
||||
Uploads = Disk
|
||||
RedirectRules = [ { From = "/here"; To = "/there"; IsRegex = false } ] }
|
||||
let! webLog = data.WebLog.FindById (WebLogId "new-weblog")
|
||||
Expect.isSome webLog "The web log should have been returned"
|
||||
let it = webLog.Value
|
||||
Expect.equal it.Id (WebLogId "new-weblog") "ID is incorrect"
|
||||
Expect.equal it.Name "Test Web Log" "Name is incorrect"
|
||||
Expect.equal it.Slug "test-web-log" "Slug is incorrect"
|
||||
Expect.isNone it.Subtitle "Subtitle is incorrect"
|
||||
Expect.equal it.DefaultPage "" "Default page is incorrect"
|
||||
Expect.equal it.PostsPerPage 7 "Posts per page is incorrect"
|
||||
Expect.equal it.ThemeId (ThemeId "default") "Theme ID is incorrect"
|
||||
Expect.equal it.UrlBase "https://example.com/new" "URL base is incorrect"
|
||||
Expect.equal it.TimeZone "America/Los_Angeles" "Time zone is incorrect"
|
||||
Expect.isTrue it.AutoHtmx "Auto htmx flag is incorrect"
|
||||
Expect.equal it.Uploads Disk "Upload destination is incorrect"
|
||||
Expect.equal it.RedirectRules [ { From = "/here"; To = "/there"; IsRegex = false } ] "Redirect rules are incorrect"
|
||||
let rss = it.Rss
|
||||
Expect.isTrue rss.IsFeedEnabled "Is feed enabled flag is incorrect"
|
||||
Expect.equal rss.FeedName "my-feed.xml" "Feed name is incorrect"
|
||||
Expect.isNone rss.ItemsInFeed "Items in feed is incorrect"
|
||||
Expect.isFalse rss.IsCategoryEnabled "Is category enabled flag is incorrect"
|
||||
Expect.isFalse rss.IsTagEnabled "Is tag enabled flag is incorrect"
|
||||
Expect.equal rss.Copyright (Some "go for it") "Copyright is incorrect"
|
||||
Expect.isEmpty rss.CustomFeeds "Custom feeds are incorrect"
|
||||
}
|
||||
|
||||
let ``All succeeds`` (data: IData) = task {
|
||||
let! webLogs = data.WebLog.All()
|
||||
Expect.hasLength webLogs 2 "There should have been 2 web logs returned"
|
||||
for webLog in webLogs do
|
||||
Expect.contains [ rootId; WebLogId "new-weblog" ] webLog.Id $"Unexpected web log returned ({webLog.Id})"
|
||||
}
|
||||
|
||||
let ``FindByHost succeeds when a web log is found`` (data: IData) = task {
|
||||
let! webLog = data.WebLog.FindByHost "http://localhost:8081"
|
||||
Expect.isSome webLog "A web log should have been returned"
|
||||
Expect.equal webLog.Value.Id rootId "The wrong web log was returned"
|
||||
}
|
||||
|
||||
let ``FindByHost succeeds when a web log is not found`` (data: IData) = task {
|
||||
let! webLog = data.WebLog.FindByHost "https://test.units"
|
||||
Expect.isNone webLog "There should not have been a web log returned"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a web log is found`` (data: IData) = task {
|
||||
let! webLog = data.WebLog.FindById rootId
|
||||
Expect.isSome webLog "There should have been a web log returned"
|
||||
let it = webLog.Value
|
||||
Expect.equal it.Id rootId "ID is incorrect"
|
||||
Expect.equal it.Name "Root WebLog" "Name is incorrect"
|
||||
Expect.equal it.Slug "root-weblog" "Slug is incorrect"
|
||||
Expect.equal it.Subtitle (Some "This is the main one") "Subtitle is incorrect"
|
||||
Expect.equal it.DefaultPage "posts" "Default page is incorrect"
|
||||
Expect.equal it.PostsPerPage 9 "Posts per page is incorrect"
|
||||
Expect.equal it.ThemeId (ThemeId "default") "Theme ID is incorrect"
|
||||
Expect.equal it.UrlBase "http://localhost:8081" "URL base is incorrect"
|
||||
Expect.equal it.TimeZone "America/Denver" "Time zone is incorrect"
|
||||
Expect.isTrue it.AutoHtmx "Auto htmx flag is incorrect"
|
||||
Expect.equal it.Uploads Database "Upload destination is incorrect"
|
||||
Expect.isEmpty it.RedirectRules "Redirect rules are incorrect"
|
||||
let rss = it.Rss
|
||||
Expect.isTrue rss.IsFeedEnabled "Is feed enabled flag is incorrect"
|
||||
Expect.equal rss.FeedName "feed" "Feed name is incorrect"
|
||||
Expect.equal rss.ItemsInFeed (Some 7) "Items in feed is incorrect"
|
||||
Expect.isTrue rss.IsCategoryEnabled "Is category enabled flag is incorrect"
|
||||
Expect.isTrue rss.IsTagEnabled "Is tag enabled flag is incorrect"
|
||||
Expect.equal rss.Copyright (Some "CC40-NC-BY") "Copyright is incorrect"
|
||||
Expect.hasLength rss.CustomFeeds 1 "There should be 1 custom feed"
|
||||
Expect.equal rss.CustomFeeds[0].Id (CustomFeedId "isPQ6drbDEydxohQzaiYtQ") "Custom feed ID incorrect"
|
||||
Expect.equal rss.CustomFeeds[0].Source (Tag "podcast") "Custom feed source is incorrect"
|
||||
Expect.equal rss.CustomFeeds[0].Path (Permalink "podcast-feed") "Custom feed path is incorrect"
|
||||
Expect.isSome rss.CustomFeeds[0].Podcast "There should be podcast settings for this custom feed"
|
||||
let pod = rss.CustomFeeds[0].Podcast.Value
|
||||
Expect.equal pod.Title "Root Podcast" "Podcast title is incorrect"
|
||||
Expect.equal pod.ItemsInFeed 23 "Podcast items in feed is incorrect"
|
||||
Expect.equal pod.Summary "All things that happen in the domain root" "Podcast summary is incorrect"
|
||||
Expect.equal pod.DisplayedAuthor "Podcaster Extraordinaire" "Podcast author is incorrect"
|
||||
Expect.equal pod.Email "podcaster@example.com" "Podcast e-mail is incorrect"
|
||||
Expect.equal pod.ImageUrl (Permalink "images/cover-art.png") "Podcast image URL is incorrect"
|
||||
Expect.equal pod.AppleCategory "Fiction" "Podcast Apple category is incorrect"
|
||||
Expect.equal pod.AppleSubcategory (Some "Drama") "Podcast Apple subcategory is incorrect"
|
||||
Expect.equal pod.Explicit No "Podcast explicit rating is incorrect"
|
||||
Expect.equal pod.DefaultMediaType (Some "audio/mpeg") "Podcast default media type is incorrect"
|
||||
Expect.equal pod.MediaBaseUrl (Some "https://media.example.com/root/") "Podcast media base URL is incorrect"
|
||||
Expect.equal pod.PodcastGuid (Some (Guid.Parse "10fd7f79-c719-4e1d-9da7-10405dd4fd96")) "Podcast GUID is incorrect"
|
||||
Expect.equal pod.FundingUrl (Some "https://example.com/support-us") "Podcast funding URL is incorrect"
|
||||
Expect.equal pod.FundingText (Some "Support Our Work") "Podcast funding text is incorrect"
|
||||
Expect.equal pod.Medium (Some Newsletter) "Podcast medium is incorrect"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a web log is not found`` (data: IData) = task {
|
||||
let! webLog = data.WebLog.FindById (WebLogId "no-web-log")
|
||||
Expect.isNone webLog "There should not have been a web log returned"
|
||||
}
|
||||
|
||||
let ``UpdateRedirectRules succeeds when the web log exists`` (data: IData) = task {
|
||||
let! webLog = data.WebLog.FindById (WebLogId "new-weblog")
|
||||
Expect.isSome webLog "The test web log should have been returned"
|
||||
do! data.WebLog.UpdateRedirectRules
|
||||
{ webLog.Value with
|
||||
RedirectRules = { From = "/now"; To = "/later"; IsRegex = false } :: webLog.Value.RedirectRules }
|
||||
let! updated = data.WebLog.FindById (WebLogId "new-weblog")
|
||||
Expect.isSome updated "The updated web log should have been returned"
|
||||
Expect.equal
|
||||
updated.Value.RedirectRules
|
||||
[ { From = "/now"; To = "/later"; IsRegex = false }; { From = "/here"; To = "/there"; IsRegex = false } ]
|
||||
"Redirect rules not updated correctly"
|
||||
}
|
||||
|
||||
let ``UpdateRedirectRules succeeds when the web log does not exist`` (data: IData) = task {
|
||||
do! data.WebLog.UpdateRedirectRules { WebLog.Empty with Id = WebLogId "no-rules" }
|
||||
Expect.isTrue true "This not raising an exception is the test"
|
||||
}
|
||||
|
||||
let ``UpdateRssOptions succeeds when the web log exists`` (data: IData) = task {
|
||||
let! webLog = data.WebLog.FindById rootId
|
||||
Expect.isSome webLog "The root web log should have been returned"
|
||||
do! data.WebLog.UpdateRssOptions { webLog.Value with Rss = { webLog.Value.Rss with CustomFeeds = [] } }
|
||||
let! updated = data.WebLog.FindById rootId
|
||||
Expect.isSome updated "The updated web log should have been returned"
|
||||
Expect.isEmpty updated.Value.Rss.CustomFeeds "RSS options not updated correctly"
|
||||
}
|
||||
|
||||
let ``UpdateRssOptions succeeds when the web log does not exist`` (data: IData) = task {
|
||||
do! data.WebLog.UpdateRssOptions { WebLog.Empty with Id = WebLogId "rss-less" }
|
||||
Expect.isTrue true "This not raising an exception is the test"
|
||||
}
|
||||
|
||||
let ``UpdateSettings succeeds when the web log exists`` (data: IData) = task {
|
||||
let! webLog = data.WebLog.FindById rootId
|
||||
Expect.isSome webLog "The root web log should have been returned"
|
||||
do! data.WebLog.UpdateSettings { webLog.Value with AutoHtmx = false; Subtitle = None }
|
||||
let! updated = data.WebLog.FindById rootId
|
||||
Expect.isSome updated "The updated web log should have been returned"
|
||||
Expect.isFalse updated.Value.AutoHtmx "Auto htmx flag not updated correctly"
|
||||
Expect.isNone updated.Value.Subtitle "Subtitle not updated correctly"
|
||||
}
|
||||
|
||||
let ``UpdateSettings succeeds when the web log does not exist`` (data: IData) = task {
|
||||
do! data.WebLog.UpdateRedirectRules { WebLog.Empty with Id = WebLogId "no-settings" }
|
||||
let! webLog = data.WebLog.FindById (WebLogId "no-settings")
|
||||
Expect.isNone webLog "Updating settings should not have created a web log"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when the web log exists`` (data: IData) = task {
|
||||
do! data.WebLog.Delete rootId
|
||||
let! cats = data.Category.FindByWebLog rootId
|
||||
Expect.isEmpty cats "There should be no categories remaining"
|
||||
let! pages = data.Page.FindFullByWebLog rootId
|
||||
Expect.isEmpty pages "There should be no pages remaining"
|
||||
let! posts = data.Post.FindFullByWebLog rootId
|
||||
Expect.isEmpty posts "There should be no posts remaining"
|
||||
let! tagMappings = data.TagMap.FindByWebLog rootId
|
||||
Expect.isEmpty tagMappings "There should be no tag mappings remaining"
|
||||
let! uploads = data.Upload.FindByWebLog rootId
|
||||
Expect.isEmpty uploads "There should be no uploads remaining"
|
||||
let! users = data.WebLogUser.FindByWebLog rootId
|
||||
Expect.isEmpty users "There should be no users remaining"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when the web log does not exist`` (data: IData) = task {
|
||||
do! data.WebLog.Delete rootId // already deleted above
|
||||
Expect.isTrue true "This not raising an exception is the test"
|
||||
}
|
||||
184
src/MyWebLog.Tests/Data/WebLogUserDataTests.fs
Normal file
184
src/MyWebLog.Tests/Data/WebLogUserDataTests.fs
Normal file
@@ -0,0 +1,184 @@
|
||||
/// <summary>
|
||||
/// Integration tests for <see cref="IWebLogUserData" /> implementations
|
||||
/// </summary>
|
||||
module WebLogUserDataTests
|
||||
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open MyWebLog.Data
|
||||
open NodaTime
|
||||
|
||||
/// The ID of the root web log
|
||||
let private rootId = CategoryDataTests.rootId
|
||||
|
||||
/// The ID of the admin user
|
||||
let private adminId = WebLogUserId "5EM2rimH9kONpmd2zQkiVA"
|
||||
|
||||
/// The ID of the editor user
|
||||
let private editorId = WebLogUserId "GPbJaSOwTkKt14ZKYyveKA"
|
||||
|
||||
/// The ID of the author user
|
||||
let private authorId = WebLogUserId "iIRNLSeY0EanxRPyqGuwVg"
|
||||
|
||||
/// The ID of the user added during the run of these tests
|
||||
let private newId = WebLogUserId "new-user"
|
||||
|
||||
let ``Add succeeds`` (data: IData) = task {
|
||||
do! data.WebLogUser.Add
|
||||
{ Id = newId
|
||||
WebLogId = rootId
|
||||
Email = "new@example.com"
|
||||
FirstName = "New"
|
||||
LastName = "User"
|
||||
PreferredName = "n00b"
|
||||
PasswordHash = "hashed-password"
|
||||
Url = Some "https://example.com/~new"
|
||||
AccessLevel = Author
|
||||
CreatedOn = Noda.epoch + Duration.FromDays 365
|
||||
LastSeenOn = None }
|
||||
let! user = data.WebLogUser.FindById newId rootId
|
||||
Expect.isSome user "There should have been a user returned"
|
||||
let it = user.Value
|
||||
Expect.equal it.Id newId "ID is incorrect"
|
||||
Expect.equal it.WebLogId rootId "Web log ID is incorrect"
|
||||
Expect.equal it.Email "new@example.com" "E-mail address is incorrect"
|
||||
Expect.equal it.FirstName "New" "First name is incorrect"
|
||||
Expect.equal it.LastName "User" "Last name is incorrect"
|
||||
Expect.equal it.PreferredName "n00b" "Preferred name is incorrect"
|
||||
Expect.equal it.PasswordHash "hashed-password" "Password hash is incorrect"
|
||||
Expect.equal it.Url (Some "https://example.com/~new") "URL is incorrect"
|
||||
Expect.equal it.AccessLevel Author "Access level is incorrect"
|
||||
Expect.equal it.CreatedOn (Noda.epoch + Duration.FromDays 365) "Created on is incorrect"
|
||||
Expect.isNone it.LastSeenOn "Last seen on should not have had a value"
|
||||
}
|
||||
|
||||
let ``FindByEmail succeeds when a user is found`` (data: IData) = task {
|
||||
let! user = data.WebLogUser.FindByEmail "root@example.com" rootId
|
||||
Expect.isSome user "There should have been a user returned"
|
||||
Expect.equal user.Value.Id adminId "The wrong user was returned"
|
||||
}
|
||||
|
||||
let ``FindByEmail succeeds when a user is not found (incorrect weblog)`` (data: IData) = task {
|
||||
let! user = data.WebLogUser.FindByEmail "root@example.com" (WebLogId "other")
|
||||
Expect.isNone user "There should not have been a user returned"
|
||||
}
|
||||
|
||||
let ``FindByEmail succeeds when a user is not found (bad email)`` (data: IData) = task {
|
||||
let! user = data.WebLogUser.FindByEmail "wwwdata@example.com" rootId
|
||||
Expect.isNone user "There should not have been a user returned"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a user is found`` (data: IData) = task {
|
||||
let! user = data.WebLogUser.FindById adminId rootId
|
||||
Expect.isSome user "There should have been a user returned"
|
||||
Expect.equal user.Value.Id adminId "The wrong user was returned"
|
||||
// The remainder of field population is tested in the "Add succeeds" test above
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a user is not found (incorrect weblog)`` (data: IData) = task {
|
||||
let! user = data.WebLogUser.FindById adminId (WebLogId "not-admin")
|
||||
Expect.isNone user "There should not have been a user returned"
|
||||
}
|
||||
|
||||
let ``FindById succeeds when a user is not found (bad ID)`` (data: IData) = task {
|
||||
let! user = data.WebLogUser.FindById (WebLogUserId "tom") rootId
|
||||
Expect.isNone user "There should not have been a user returned"
|
||||
}
|
||||
|
||||
let ``FindByWebLog succeeds when users exist`` (data: IData) = task {
|
||||
let! users = data.WebLogUser.FindByWebLog rootId
|
||||
Expect.hasLength users 4 "There should have been 4 users returned"
|
||||
for user in users do
|
||||
Expect.contains [ adminId; editorId; authorId; newId ] user.Id $"Unexpected user returned ({user.Id})"
|
||||
}
|
||||
|
||||
let ``FindByWebLog succeeds when no users exist`` (data: IData) = task {
|
||||
let! users = data.WebLogUser.FindByWebLog (WebLogId "no-users")
|
||||
Expect.isEmpty users "There should have been no users returned"
|
||||
}
|
||||
|
||||
let ``FindNames succeeds when users exist`` (data: IData) = task {
|
||||
let! names = data.WebLogUser.FindNames rootId [ editorId; authorId ]
|
||||
let expected =
|
||||
[ { Name = string editorId; Value = "Edits It-Or" }; { Name = string authorId; Value = "Mister Dude" } ]
|
||||
Expect.hasLength names 2 "There should have been 2 names returned"
|
||||
for name in names do Expect.contains expected name $"Unexpected name returned ({name.Name}|{name.Value})"
|
||||
}
|
||||
|
||||
let ``FindNames succeeds when users do not exist`` (data: IData) = task {
|
||||
let! names = data.WebLogUser.FindNames rootId [ WebLogUserId "nope"; WebLogUserId "no" ]
|
||||
Expect.isEmpty names "There should have been no names returned"
|
||||
}
|
||||
|
||||
let ``SetLastSeen succeeds when the user exists`` (data: IData) = task {
|
||||
let now = Noda.now ()
|
||||
do! data.WebLogUser.SetLastSeen newId rootId
|
||||
let! user = data.WebLogUser.FindById newId rootId
|
||||
Expect.isSome user "The user should have been returned"
|
||||
let it = user.Value
|
||||
Expect.isSome it.LastSeenOn "Last seen on should have been set"
|
||||
Expect.isGreaterThanOrEqual it.LastSeenOn.Value now "The last seen on date/time was not set correctly"
|
||||
}
|
||||
|
||||
let ``SetLastSeen succeeds when the user does not exist`` (data: IData) = task {
|
||||
do! data.WebLogUser.SetLastSeen (WebLogUserId "matt") rootId
|
||||
Expect.isTrue true "This not raising an exception is the test"
|
||||
}
|
||||
|
||||
let ``Update succeeds when the user exists`` (data: IData) = task {
|
||||
let! currentUser = data.WebLogUser.FindById newId rootId
|
||||
Expect.isSome currentUser "The current user should have been found"
|
||||
do! data.WebLogUser.Update
|
||||
{ currentUser.Value with
|
||||
Email = "newish@example.com"
|
||||
FirstName = "New-ish"
|
||||
LastName = "User-ish"
|
||||
PreferredName = "n00b-ish"
|
||||
PasswordHash = "hashed-ish-password"
|
||||
Url = None
|
||||
AccessLevel = Editor }
|
||||
let! updated = data.WebLogUser.FindById newId rootId
|
||||
Expect.isSome updated "The updated user should have been returned"
|
||||
let it = updated.Value
|
||||
Expect.equal it.Id newId "ID is incorrect"
|
||||
Expect.equal it.WebLogId rootId "Web log ID is incorrect"
|
||||
Expect.equal it.Email "newish@example.com" "E-mail address is incorrect"
|
||||
Expect.equal it.FirstName "New-ish" "First name is incorrect"
|
||||
Expect.equal it.LastName "User-ish" "Last name is incorrect"
|
||||
Expect.equal it.PreferredName "n00b-ish" "Preferred name is incorrect"
|
||||
Expect.equal it.PasswordHash "hashed-ish-password" "Password hash is incorrect"
|
||||
Expect.isNone it.Url "URL is incorrect"
|
||||
Expect.equal it.AccessLevel Editor "Access level is incorrect"
|
||||
Expect.equal it.CreatedOn (Noda.epoch + Duration.FromDays 365) "Created on is incorrect"
|
||||
Expect.isSome it.LastSeenOn "Last seen on should have had a value"
|
||||
}
|
||||
|
||||
let ``Update succeeds when the user does not exist`` (data: IData) = task {
|
||||
do! data.WebLogUser.Update { WebLogUser.Empty with Id = WebLogUserId "nothing"; WebLogId = rootId }
|
||||
let! updated = data.WebLogUser.FindById (WebLogUserId "nothing") rootId
|
||||
Expect.isNone updated "The update of a missing user should not have created the user"
|
||||
}
|
||||
|
||||
let ``Delete fails when the user is the author of a page`` (data: IData) = task {
|
||||
match! data.WebLogUser.Delete adminId rootId with
|
||||
| Ok _ -> Expect.isTrue false "Deletion should have failed because the user is a page author"
|
||||
| Error msg -> Expect.equal msg "User has pages or posts; cannot delete" "Error message is incorrect"
|
||||
}
|
||||
|
||||
let ``Delete fails when the user is the author of a post`` (data: IData) = task {
|
||||
match! data.WebLogUser.Delete authorId rootId with
|
||||
| Ok _ -> Expect.isTrue false "Deletion should have failed because the user is a post author"
|
||||
| Error msg -> Expect.equal msg "User has pages or posts; cannot delete" "Error message is incorrect"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when the user is not an author`` (data: IData) = task {
|
||||
match! data.WebLogUser.Delete newId rootId with
|
||||
| Ok _ -> Expect.isTrue true "This is the expected outcome"
|
||||
| Error msg -> Expect.isTrue false $"Deletion unexpectedly failed (message {msg})"
|
||||
}
|
||||
|
||||
let ``Delete succeeds when the user does not exist`` (data: IData) = task {
|
||||
match! data.WebLogUser.Delete newId rootId with // already deleted above
|
||||
| Ok _ -> Expect.isTrue false "Deletion should have failed because the user does not exist"
|
||||
| Error msg -> Expect.equal msg "User does not exist" "Error message is incorrect"
|
||||
}
|
||||
87
src/MyWebLog.Tests/Domain/DataTypesTests.fs
Normal file
87
src/MyWebLog.Tests/Domain/DataTypesTests.fs
Normal file
@@ -0,0 +1,87 @@
|
||||
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 ]
|
||||
415
src/MyWebLog.Tests/Domain/SupportTypesTests.fs
Normal file
415
src/MyWebLog.Tests/Domain/SupportTypesTests.fs
Normal file
@@ -0,0 +1,415 @@
|
||||
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"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// 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
|
||||
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
|
||||
]
|
||||
1246
src/MyWebLog.Tests/Domain/ViewModelsTests.fs
Normal file
1246
src/MyWebLog.Tests/Domain/ViewModelsTests.fs
Normal file
File diff suppressed because it is too large
Load Diff
38
src/MyWebLog.Tests/MyWebLog.Tests.fsproj
Normal file
38
src/MyWebLog.Tests/MyWebLog.Tests.fsproj
Normal file
@@ -0,0 +1,38 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Domain\SupportTypesTests.fs" />
|
||||
<Compile Include="Domain\DataTypesTests.fs" />
|
||||
<Compile Include="Domain\ViewModelsTests.fs" />
|
||||
<Compile Include="Data\ConvertersTests.fs" />
|
||||
<Compile Include="Data\UtilsTests.fs" />
|
||||
<Compile Include="Data\CategoryDataTests.fs" />
|
||||
<Compile Include="Data\PageDataTests.fs" />
|
||||
<Compile Include="Data\PostDataTests.fs" />
|
||||
<Compile Include="Data\TagMapDataTests.fs" />
|
||||
<Compile Include="Data\ThemeDataTests.fs" />
|
||||
<Compile Include="Data\UploadDataTests.fs" />
|
||||
<Compile Include="Data\WebLogUserDataTests.fs" />
|
||||
<Compile Include="Data\WebLogDataTests.fs" />
|
||||
<Compile Include="Data\RethinkDbDataTests.fs" />
|
||||
<Compile Include="Data\SQLiteDataTests.fs" />
|
||||
<Compile Include="Data\PostgresDataTests.fs" />
|
||||
<Compile Include="Program.fs" />
|
||||
<None Include="root-weblog.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Expecto" Version="10.2.1" />
|
||||
<PackageReference Include="ThrowawayDb.Postgres" Version="1.4.0" />
|
||||
<PackageReference Update="FSharp.Core" Version="8.0.200" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MyWebLog\MyWebLog.fsproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
31
src/MyWebLog.Tests/Program.fs
Normal file
31
src/MyWebLog.Tests/Program.fs
Normal file
@@ -0,0 +1,31 @@
|
||||
open Expecto
|
||||
|
||||
/// Whether to only run RethinkDB data tests
|
||||
let rethinkOnly = (RethinkDbDataTests.env "RETHINK_ONLY" "0") = "1"
|
||||
|
||||
/// Whether to only run SQLite data tests
|
||||
let sqliteOnly = (RethinkDbDataTests.env "SQLITE_ONLY" "0") = "1"
|
||||
|
||||
/// Whether to only run PostgreSQL data tests
|
||||
let postgresOnly = (RethinkDbDataTests.env "PG_ONLY" "0") = "1"
|
||||
|
||||
/// Whether any of the data tests are being isolated
|
||||
let dbOnly = rethinkOnly || sqliteOnly || postgresOnly
|
||||
|
||||
/// Whether to only run the unit tests (skip database/integration tests)
|
||||
let unitOnly = (RethinkDbDataTests.env "UNIT_ONLY" "0") = "1"
|
||||
|
||||
let allTests = testList "MyWebLog" [
|
||||
if not dbOnly then testList "Domain" [ SupportTypesTests.all; DataTypesTests.all; ViewModelsTests.all ]
|
||||
if not unitOnly then
|
||||
testList "Data" [
|
||||
if not dbOnly then ConvertersTests.all
|
||||
if not dbOnly then UtilsTests.all
|
||||
if not dbOnly || (dbOnly && rethinkOnly) then RethinkDbDataTests.all
|
||||
if not dbOnly || (dbOnly && sqliteOnly) then SQLiteDataTests.all
|
||||
if not dbOnly || (dbOnly && postgresOnly) then PostgresDataTests.all
|
||||
]
|
||||
]
|
||||
|
||||
[<EntryPoint>]
|
||||
let main args = runTestsWithCLIArgs [] args allTests
|
||||
380
src/MyWebLog.Tests/root-weblog.json
Normal file
380
src/MyWebLog.Tests/root-weblog.json
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user