From 2c052c18139433afb1c09652706180324c43716c Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sat, 6 Jan 2024 17:04:05 -0500 Subject: [PATCH] Add test project - Create /data directory if necessary (#38) --- src/MyWebLog.Data/SQLiteData.fs | 1 + src/MyWebLog.Domain/ViewModels.fs | 5 + src/MyWebLog.Tests/Domain.fs | 119 +++++++++++++++++++++++ src/MyWebLog.Tests/MyWebLog.Tests.fsproj | 20 ++++ src/MyWebLog.Tests/Program.fs | 9 ++ src/MyWebLog.sln | 6 ++ src/MyWebLog/Program.fs | 3 +- 7 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 src/MyWebLog.Tests/Domain.fs create mode 100644 src/MyWebLog.Tests/MyWebLog.Tests.fsproj create mode 100644 src/MyWebLog.Tests/Program.fs diff --git a/src/MyWebLog.Data/SQLiteData.fs b/src/MyWebLog.Data/SQLiteData.fs index 33fb56b..52f6de2 100644 --- a/src/MyWebLog.Data/SQLiteData.fs +++ b/src/MyWebLog.Data/SQLiteData.fs @@ -214,6 +214,7 @@ type SQLiteData(conn: SqliteConnection, log: ILogger, ser: JsonSeria |> Option.map (Utils.deserialize ser) ChapterFile = Map.tryString "chapter_file" epRdr ChapterType = Map.tryString "chapter_type" epRdr + ChapterWaypoints = None TranscriptUrl = Map.tryString "transcript_url" epRdr TranscriptType = Map.tryString "transcript_type" epRdr TranscriptLang = Map.tryString "transcript_lang" epRdr diff --git a/src/MyWebLog.Domain/ViewModels.fs b/src/MyWebLog.Domain/ViewModels.fs index db7f8d8..3b8a761 100644 --- a/src/MyWebLog.Domain/ViewModels.fs +++ b/src/MyWebLog.Domain/ViewModels.fs @@ -656,6 +656,9 @@ type EditPostModel = { /// The type of the chapter file (optional; defaults to application/json+chapters if chapterFile is provided) ChapterType: string + /// Whether the chapter file (or chapters) contains/contain waypoints + ContainsWaypoints: bool + /// The URL for the transcript (may be permalink; optional) TranscriptUrl: string @@ -714,6 +717,7 @@ type EditPostModel = { Explicit = defaultArg (episode.Explicit |> Option.map string) "" ChapterFile = defaultArg episode.ChapterFile "" ChapterType = defaultArg episode.ChapterType "" + ContainsWaypoints = defaultArg episode.ChapterWaypoints false TranscriptUrl = defaultArg episode.TranscriptUrl "" TranscriptType = defaultArg episode.TranscriptType "" TranscriptLang = defaultArg episode.TranscriptLang "" @@ -775,6 +779,7 @@ type EditPostModel = { Chapters = match post.Episode with Some e -> e.Chapters | None -> None ChapterFile = noneIfBlank this.ChapterFile ChapterType = noneIfBlank this.ChapterType + ChapterWaypoints = if this.ContainsWaypoints then Some true else None TranscriptUrl = noneIfBlank this.TranscriptUrl TranscriptType = noneIfBlank this.TranscriptType TranscriptLang = noneIfBlank this.TranscriptLang diff --git a/src/MyWebLog.Tests/Domain.fs b/src/MyWebLog.Tests/Domain.fs new file mode 100644 index 0000000..84278ae --- /dev/null +++ b/src/MyWebLog.Tests/Domain.fs @@ -0,0 +1,119 @@ +module Domain + +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 "\"Author\" succeeds" { + Expect.equal Author (AccessLevel.Parse "Author") "Author not parsed correctly" + } + test "\"Editor\" succeeds" { + Expect.equal Editor (AccessLevel.Parse "Editor") "Editor not parsed correctly" + } + test "\"WebLogAdmin\" succeeds" { + Expect.equal WebLogAdmin (AccessLevel.Parse "WebLogAdmin") "WebLogAdmin not parsed correctly" + } + test "\"Administrator\" succeeds" { + Expect.equal Administrator (AccessLevel.Parse "Administrator") "Administrator not parsed correctly" + } + test "fails when given an unrecognized value" { + Expect.throwsT + (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" + } + ] + ] + +/// All tests for the Domain namespace +let all = testList "Domain" [ nodaTests; accessLevelTests ] diff --git a/src/MyWebLog.Tests/MyWebLog.Tests.fsproj b/src/MyWebLog.Tests/MyWebLog.Tests.fsproj new file mode 100644 index 0000000..1cae610 --- /dev/null +++ b/src/MyWebLog.Tests/MyWebLog.Tests.fsproj @@ -0,0 +1,20 @@ + + + + Exe + + + + + + + + + + + + + + + + diff --git a/src/MyWebLog.Tests/Program.fs b/src/MyWebLog.Tests/Program.fs new file mode 100644 index 0000000..5a5a4be --- /dev/null +++ b/src/MyWebLog.Tests/Program.fs @@ -0,0 +1,9 @@ +open Expecto + +let allTests = + testList + "MyWebLog" + [ Domain.all ] + +[] +let main args = runTestsWithCLIArgs [] args allTests diff --git a/src/MyWebLog.sln b/src/MyWebLog.sln index a594b6e..973bd50 100644 --- a/src/MyWebLog.sln +++ b/src/MyWebLog.sln @@ -9,6 +9,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "MyWebLog.Data", "MyWebLog.D EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "MyWebLog", "MyWebLog\MyWebLog.fsproj", "{5655B63D-429F-4CCD-A14C-FBD74D987ECB}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "MyWebLog.Tests", "MyWebLog.Tests\MyWebLog.Tests.fsproj", "{D927D39F-26EC-4A54-989A-9D474F232398}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,10 @@ Global {5655B63D-429F-4CCD-A14C-FBD74D987ECB}.Debug|Any CPU.Build.0 = Debug|Any CPU {5655B63D-429F-4CCD-A14C-FBD74D987ECB}.Release|Any CPU.ActiveCfg = Release|Any CPU {5655B63D-429F-4CCD-A14C-FBD74D987ECB}.Release|Any CPU.Build.0 = Release|Any CPU + {D927D39F-26EC-4A54-989A-9D474F232398}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D927D39F-26EC-4A54-989A-9D474F232398}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D927D39F-26EC-4A54-989A-9D474F232398}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D927D39F-26EC-4A54-989A-9D474F232398}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/MyWebLog/Program.fs b/src/MyWebLog/Program.fs index d9918f1..293fb17 100644 --- a/src/MyWebLog/Program.fs +++ b/src/MyWebLog/Program.fs @@ -50,6 +50,7 @@ type RedirectRuleMiddleware(next: RequestDelegate, log: ILogger ignore createSQLite "Data Source=./data/myweblog.db;Cache=Shared" @@ -122,7 +124,6 @@ let showHelp () = Task.FromResult() -open System.IO open BitBadger.AspNetCore.CanonicalDomains open Giraffe open Giraffe.EndpointRouting