diff --git a/src/AVPRIndex/AVPRIndex.fsproj b/src/AVPRIndex/AVPRIndex.fsproj index fb7b469..1b61b5b 100644 --- a/src/AVPRIndex/AVPRIndex.fsproj +++ b/src/AVPRIndex/AVPRIndex.fsproj @@ -16,7 +16,7 @@ git $([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/RELEASE_NOTES.md")) README.md - 0.1.3 + 0.2.0 diff --git a/src/AVPRIndex/Domain.fs b/src/AVPRIndex/Domain.fs index 8d224a0..8577af8 100644 --- a/src/AVPRIndex/Domain.fs +++ b/src/AVPRIndex/Domain.fs @@ -11,6 +11,75 @@ module Domain = let jsonSerializerOptions = JsonSerializerOptions(WriteIndented = true) + type SemVer() = + member val Major = -1 with get,set + member val Minor = -1 with get,set + member val Patch = -1 with get,set + member val PreRelease = "" with get,set + member val BuildMetadata = "" with get,set + + override this.GetHashCode() = + hash ( + this.Major, + this.Minor, + this.Patch, + this.PreRelease, + this.BuildMetadata + ) + + override this.Equals(other) = + match other with + | :? SemVer as s -> + ( + this.Major, + this.Minor, + this.Patch, + this.PreRelease, + this.BuildMetadata + ) = ( + s.Major, + s.Minor, + s.Patch, + s.PreRelease, + s.BuildMetadata + ) + | _ -> false + + static member create ( + major: int, + minor: int, + patch: int, + ?PreRelease: string, + ?BuildMetadata: string + ) = + let tmp = SemVer( + Major = major, + Minor = minor, + Patch = patch + ) + PreRelease |> Option.iter (fun x -> tmp.PreRelease <- x) + BuildMetadata |> Option.iter (fun x -> tmp.BuildMetadata <- x) + tmp + + static member tryParse (version: string) = + match version |> Globals.SEMVER_REGEX.Match |> fun m -> m.Success, m.Groups with + | true, groups -> + let major = groups.["major"].Value |> int + let minor = groups.["minor"].Value |> int + let patch = groups.["patch"].Value |> int + let preRelease = groups.["prerelease"].Value + let buildMetadata = groups.["buildmetadata"].Value + Some(SemVer.create(major, minor, patch, preRelease, buildMetadata)) + | _ -> None + + static member toString (semVer: SemVer) = + match (semVer.PreRelease, semVer.BuildMetadata) with + | (pr, bm) when pr <> "" && bm <> "" -> $"{semVer.Major}.{semVer.Minor}.{semVer.Patch}-{pr}+{bm}" + | (pr, bm) when pr <> "" && bm = "" -> $"{semVer.Major}.{semVer.Minor}.{semVer.Patch}-{pr}" + | (pr, bm) when pr = "" && bm <> "" -> $"{semVer.Major}.{semVer.Minor}.{semVer.Patch}+{bm}" + | _ -> $"{semVer.Major}.{semVer.Minor}.{semVer.Patch}" + + type Author() = member val FullName = "" with get,set member val Email = "" with get,set @@ -43,16 +112,16 @@ module Domain = static member create ( fullName: string, - ?email: string, - ?affiliation: string, - ?affiliationLink: string + ?Email: string, + ?Affiliation: string, + ?AffiliationLink: string ) = let tmp = Author( FullName = fullName ) - email |> Option.iter (fun x -> tmp.Email <- x) - affiliation |> Option.iter (fun x -> tmp.Affiliation <- x) - affiliationLink |> Option.iter (fun x -> tmp.AffiliationLink <- x) + Email |> Option.iter (fun x -> tmp.Email <- x) + Affiliation |> Option.iter (fun x -> tmp.Affiliation <- x) + AffiliationLink |> Option.iter (fun x -> tmp.AffiliationLink <- x) tmp @@ -85,12 +154,12 @@ module Domain = static member create ( name: string, - ?termSourceRef: string, - ?termAccessionNumber: string + ?TermSourceRef: string, + ?TermAccessionNumber: string ) = let tmp = new OntologyAnnotation(Name = name) - termSourceRef |> Option.iter (fun x -> tmp.TermSourceREF <- x) - termAccessionNumber |> Option.iter (fun x -> tmp.TermAccessionNumber <- x) + TermSourceRef |> Option.iter (fun x -> tmp.TermSourceREF <- x) + TermAccessionNumber |> Option.iter (fun x -> tmp.TermAccessionNumber <- x) tmp type ValidationPackageMetadata() = @@ -101,6 +170,8 @@ module Domain = member val MajorVersion = -1 with get,set member val MinorVersion = -1 with get,set member val PatchVersion = -1 with get,set + member val PreReleaseVersionSuffix = "" with get,set + member val BuildMetadataVersionSuffix = "" with get,set // optional fields member val Publish = false with get,set member val Authors: Author [] = Array.empty with get,set @@ -116,6 +187,8 @@ module Domain = this.MajorVersion, this.MinorVersion, this.PatchVersion, + this.PreReleaseVersionSuffix, + this.BuildMetadataVersionSuffix, this.Publish, this.Authors, this.Tags, @@ -133,6 +206,8 @@ module Domain = this.MajorVersion, this.MinorVersion, this.PatchVersion, + this.PreReleaseVersionSuffix, + this.BuildMetadataVersionSuffix, this.Publish, this.Authors, this.Tags, @@ -144,7 +219,9 @@ module Domain = vpm.Description, vpm.MajorVersion, vpm.MinorVersion, - vpm.PatchVersion, + this.PatchVersion, + this.PreReleaseVersionSuffix, + this.BuildMetadataVersionSuffix, vpm.Publish, vpm.Authors, vpm.Tags, @@ -160,6 +237,8 @@ module Domain = majorVersion: int, minorVersion: int, patchVersion: int, + ?PreReleaseVersionSuffix: string, + ?BuildMetadataVersionSuffix: string, ?Publish: bool, ?Authors: Author [], ?Tags: OntologyAnnotation [], @@ -175,6 +254,8 @@ module Domain = PatchVersion = patchVersion ) + PreReleaseVersionSuffix |> Option.iter (fun x -> tmp.PreReleaseVersionSuffix <- x) + BuildMetadataVersionSuffix |> Option.iter (fun x -> tmp.BuildMetadataVersionSuffix <- x) Publish |> Option.iter (fun x -> tmp.Publish <- x) Authors |> Option.iter (fun x -> tmp.Authors <- x) Tags |> Option.iter (fun x -> tmp.Tags <- x) @@ -183,7 +264,33 @@ module Domain = tmp - static member getSemanticVersionString(m: ValidationPackageMetadata) = $"{m.MajorVersion}.{m.MinorVersion}.{m.PatchVersion}" + static member tryGetSemanticVersion(m: ValidationPackageMetadata) = + SemVer.create( + m.MajorVersion, + m.MinorVersion, + m.PatchVersion, + m.PreReleaseVersionSuffix, + m.BuildMetadataVersionSuffix + ) + |> SemVer.toString + |> SemVer.tryParse // there is no buit-in validation on the constructor/create function, so we'll take a detour via parsing roundtrip using the regex + + static member getSemanticVersion(m: ValidationPackageMetadata) = + m + |> ValidationPackageMetadata.tryGetSemanticVersion + |> Option.get + + static member tryGetSemanticVersionString(m: ValidationPackageMetadata) = + m + |> ValidationPackageMetadata.tryGetSemanticVersion + |> Option.map SemVer.toString + + static member getSemanticVersionString(m: ValidationPackageMetadata) = + m + |> ValidationPackageMetadata.tryGetSemanticVersion + |> Option.map SemVer.toString + |> Option.get + type ValidationPackageIndex = { @@ -240,7 +347,17 @@ module Domain = printfn $"Indexed Package info:{System.Environment.NewLine}{json}" printfn "" - static member getSemanticVersionString(i: ValidationPackageIndex) = $"{i.Metadata.MajorVersion}.{i.Metadata.MinorVersion}.{i.Metadata.PatchVersion}"; + static member tryGetSemanticVersion(i: ValidationPackageIndex) = + i.Metadata |> ValidationPackageMetadata.tryGetSemanticVersion + + static member getSemanticVersion(i: ValidationPackageIndex) = + i.Metadata |> ValidationPackageMetadata.getSemanticVersion + + static member tryGetSemanticVersionString(i: ValidationPackageIndex) = + i.Metadata |> ValidationPackageMetadata.tryGetSemanticVersionString + + static member getSemanticVersionString(i: ValidationPackageIndex) = + i.Metadata |> ValidationPackageMetadata.getSemanticVersionString member this.PrettyPrint() = $" {this.Metadata.Name} @ version {this.Metadata.MajorVersion}.{this.Metadata.MinorVersion}.{this.Metadata.PatchVersion}{System.Environment.NewLine}{_.Metadata.Description}{System.Environment.NewLine}Last Updated: {this.LastUpdated}{System.Environment.NewLine}" diff --git a/src/AVPRIndex/Globals.fs b/src/AVPRIndex/Globals.fs index d698711..98c601b 100644 --- a/src/AVPRIndex/Globals.fs +++ b/src/AVPRIndex/Globals.fs @@ -1,5 +1,13 @@ namespace AVPRIndex +open System.Text +open System.Text.RegularExpressions + module Globals = - let [] STAGING_AREA_RELATIVE_PATH = "StagingArea" \ No newline at end of file + let [] STAGING_AREA_RELATIVE_PATH = "StagingArea" + + // https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string + let [] SEMVER_REGEX_PATTERN = @"^(?0|[1-9]\d*)\.(?0|[1-9]\d*)\.(?0|[1-9]\d*)(?:-(?(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$" + + let SEMVER_REGEX = new Regex(SEMVER_REGEX_PATTERN) \ No newline at end of file diff --git a/src/AVPRIndex/MD5Hash.fs b/src/AVPRIndex/MD5Hash.fs index f12bc23..3a092f6 100644 --- a/src/AVPRIndex/MD5Hash.fs +++ b/src/AVPRIndex/MD5Hash.fs @@ -29,4 +29,3 @@ type Hash = path |> File.ReadAllText |> Hash.hashString - diff --git a/src/AVPRIndex/RELEASE_NOTES.md b/src/AVPRIndex/RELEASE_NOTES.md index 0ebe417..24d51da 100644 --- a/src/AVPRIndex/RELEASE_NOTES.md +++ b/src/AVPRIndex/RELEASE_NOTES.md @@ -1,3 +1,9 @@ +## v0.2.0 + +- Add `SemVer` type model for a full semantic version representation including PreRelease and Build metadata with parsing and formatting functions +- Improve functions for getting semantic version (strings) from `ValidationPackageMetadata` and `ValidationPackageIndex` types based on new `SemVer` type +- - Unify capitalization in Domain create functions + ## v0.1.3 Add `BinaryContent` module to unify package content handling across downstream libraries diff --git a/tests/IndexTests/DomainTests.fs b/tests/IndexTests/DomainTests.fs index 6250ac1..8ec5929 100644 --- a/tests/IndexTests/DomainTests.fs +++ b/tests/IndexTests/DomainTests.fs @@ -7,6 +7,100 @@ open AVPRIndex open AVPRIndex.Domain open ReferenceObjects +module SemVer = + + [] + let ``create function for mandatory fields``() = + let actual = SemVer.create(major=1, minor=0, patch=0) + Assert.Equivalent(SemVer.SemVers.mandatory, actual) + Assert.Equal(SemVer.SemVers.mandatory, actual) + + [] + let ``create function for all fields``() = + let actual = SemVer.create(major=1, minor=0, patch=0, PreRelease="alpha.1", BuildMetadata="build.1") + Assert.Equivalent(SemVer.SemVers.prereleaseAndBuildmetadata, actual) + Assert.Equal(SemVer.SemVers.prereleaseAndBuildmetadata, actual) + + [] + let ``Can parse mandatory``() = + let actual = SemVer.Strings.mandatory |> SemVer.tryParse + Assert.True(actual.IsSome) + Assert.Equivalent(SemVer.SemVers.mandatory, actual.Value) + Assert.Equal(SemVer.SemVers.mandatory, actual.Value) + + [] + let ``Can parse prerelease``() = + let actual = SemVer.Strings.prerelease |> SemVer.tryParse + Assert.True(actual.IsSome) + Assert.Equivalent(SemVer.SemVers.prerelease, actual.Value) + Assert.Equal(SemVer.SemVers.prerelease, actual.Value) + + [] + let ``Can parse buildmetadata``() = + let actual = SemVer.Strings.buildmetadata |> SemVer.tryParse + Assert.True(actual.IsSome) + Assert.Equivalent(SemVer.SemVers.buildmetadata, actual.Value) + Assert.Equal(SemVer.SemVers.buildmetadata, actual.Value) + + [] + let ``Can parse prereleaseAndBuildmetadata``() = + let actual = SemVer.Strings.prereleaseAndBuildmetadata |> SemVer.tryParse + Assert.True(actual.IsSome) + Assert.Equivalent(SemVer.SemVers.prereleaseAndBuildmetadata, actual.Value) + Assert.Equal(SemVer.SemVers.prereleaseAndBuildmetadata, actual.Value) + + [] + let ``Can parse major version 0``() = + let actual = SemVer.Strings.majorZero |> SemVer.tryParse + Assert.True(actual.IsSome) + Assert.Equivalent(SemVer.SemVers.majorZero, actual.Value) + Assert.Equal(SemVer.SemVers.majorZero, actual.Value) + + [] + let ``Cannot parse leading 0 in major``() = + let actual = SemVer.Strings.invalidLeadingZero |> SemVer.tryParse + Assert.True(actual.IsNone) + + [] + let ``Cannot parse leading 0 in minor``() = + let actual = SemVer.Strings.invalidLeadingZeroMinor |> SemVer.tryParse + Assert.True(actual.IsNone) + + [] + let ``Cannot parse leading 0 in patch``() = + let actual = SemVer.Strings.invalidLeadingZeroPatch |> SemVer.tryParse + Assert.True(actual.IsNone) + + [] + let ``Cannot parse leading 0 in prerelease``() = + let actual = SemVer.Strings.invalidLeadingZeroPrerelease |> SemVer.tryParse + Assert.True(actual.IsNone) + + [] + let ``Can write mandatory``() = + let actual = SemVer.SemVers.mandatory |> SemVer.toString + Assert.Equivalent(SemVer.Strings.mandatory, actual) + Assert.Equal(SemVer.Strings.mandatory, actual) + + [] + let ``Can write prerelease``() = + let actual = SemVer.SemVers.prerelease |> SemVer.toString + Assert.Equivalent(SemVer.Strings.prerelease, actual) + Assert.Equal(SemVer.Strings.prerelease, actual) + + [] + let ``Can write buildmetadata``() = + let actual = SemVer.SemVers.buildmetadata |> SemVer.toString + Assert.Equivalent(SemVer.Strings.buildmetadata, actual) + Assert.Equal(SemVer.Strings.buildmetadata, actual) + + [] + let ``Can write prereleaseAndBuildmetadata``() = + let actual = SemVer.SemVers.prereleaseAndBuildmetadata |> SemVer.toString + Assert.Equivalent(SemVer.Strings.prereleaseAndBuildmetadata, actual) + Assert.Equal(SemVer.Strings.prereleaseAndBuildmetadata, actual) + + module Author = [] @@ -63,6 +157,8 @@ module ValidationPackageMetadata = majorVersion = 1, minorVersion = 0, patchVersion = 0, + PreReleaseVersionSuffix = "alpha.1", + BuildMetadataVersionSuffix = "build.1", Publish = true, Authors = [| Author.create( @@ -82,4 +178,52 @@ module ValidationPackageMetadata = ReleaseNotes = "releasenotes", CQCHookEndpoint = "hookendpoint" ) - Assert.Equivalent(ValidationPackageMetadata.allFields, actual) \ No newline at end of file + Assert.Equivalent(ValidationPackageMetadata.allFields, actual) + + [] + let ``tryGetSemanticVersion from valid package metadata with mandatory fields``() = + let actual = ValidationPackageMetadata.mandatoryFields |> ValidationPackageMetadata.tryGetSemanticVersion + Assert.True(actual.IsSome) + Assert.Equivalent(SemVer.SemVers.mandatory, actual.Value) + Assert.Equal(SemVer.SemVers.mandatory, actual.Value) + + [] + let ``getSemanticVersion from valid package metadata with mandatory fields``() = + let actual = ValidationPackageMetadata.mandatoryFields |> ValidationPackageMetadata.getSemanticVersion + Assert.Equivalent(SemVer.SemVers.mandatory, actual) + Assert.Equal(SemVer.SemVers.mandatory, actual) + + [] + let ``tryGetSemanticVersionString from valid package metadata with mandatory fields``() = + let actual = ValidationPackageMetadata.mandatoryFields |> ValidationPackageMetadata.tryGetSemanticVersionString + Assert.True(actual.IsSome) + Assert.Equal(SemVer.Strings.mandatory, actual.Value) + + [] + let ``getSemanticVersionString from valid package metadata with mandatory fields``() = + let actual = ValidationPackageMetadata.mandatoryFields |> ValidationPackageMetadata.getSemanticVersionString + Assert.Equal(SemVer.Strings.mandatory, actual) + + [] + let ``tryGetSemanticVersion from valid package metadata with all fields``() = + let actual = ValidationPackageMetadata.allFields |> ValidationPackageMetadata.tryGetSemanticVersion + Assert.True(actual.IsSome) + Assert.Equivalent(SemVer.SemVers.prereleaseAndBuildmetadata, actual.Value) + Assert.Equal(SemVer.SemVers.prereleaseAndBuildmetadata, actual.Value) + + [] + let ``getSemanticVersion from valid package metadata with all fields``() = + let actual = ValidationPackageMetadata.allFields |> ValidationPackageMetadata.getSemanticVersion + Assert.Equivalent(SemVer.SemVers.prereleaseAndBuildmetadata, actual) + Assert.Equal(SemVer.SemVers.prereleaseAndBuildmetadata, actual) + + [] + let ``tryGetSemanticVersionString from valid package metadata with all fields``() = + let actual = ValidationPackageMetadata.allFields |> ValidationPackageMetadata.tryGetSemanticVersionString + Assert.True(actual.IsSome) + Assert.Equal(SemVer.Strings.prereleaseAndBuildmetadata, actual.Value) + + [] + let ``getSemanticVersionString from valid package metadata with all fields``() = + let actual = ValidationPackageMetadata.allFields |> ValidationPackageMetadata.getSemanticVersionString + Assert.Equal(SemVer.Strings.prereleaseAndBuildmetadata, actual) \ No newline at end of file diff --git a/tests/IndexTests/ReferenceObjects.fs b/tests/IndexTests/ReferenceObjects.fs index 9c8f56d..ae28963 100644 --- a/tests/IndexTests/ReferenceObjects.fs +++ b/tests/IndexTests/ReferenceObjects.fs @@ -6,6 +6,32 @@ open AVPRIndex.Domain let testDate = System.DateTimeOffset.Parse("01/01/2024") +module SemVer = + + module Strings = + + let mandatory = "1.0.0" + let prerelease = "1.0.0-alpha.1" + let buildmetadata = "1.0.0+build.1" + let prereleaseAndBuildmetadata = "1.0.0-alpha.1+build.1" + let majorZero = "0.1.2" + + let fixtureFile = "2.0.0-alpha.1+build.1" + + let invalidLeadingZero = "01.0.0" + let invalidLeadingZeroMinor = "1.01.0" + let invalidLeadingZeroPatch = "1.0.01" + let invalidLeadingZeroPrerelease = "1.0.0-01" + + module SemVers = + + let mandatory = SemVer(Major = 1, Minor = 0, Patch = 0) + let prerelease = SemVer(Major = 1, Minor = 0, Patch = 0, PreRelease = "alpha.1") + let buildmetadata = SemVer(Major = 1, Minor = 0, Patch = 0, BuildMetadata = "build.1") + let prereleaseAndBuildmetadata = SemVer(Major = 1, Minor = 0, Patch = 0, PreRelease = "alpha.1",BuildMetadata = "build.1") + let majorZero = SemVer(Major = 0, Minor = 1, Patch = 2) + let fixtureFile = SemVer(Major = 2, Minor = 0, Patch = 0, PreRelease = "alpha.1", BuildMetadata = "build.1") + module Hash = module Input = @@ -30,13 +56,13 @@ module Hash = module CommentFrontmatter = let validMandatoryFrontmatter = "2A29D85A29D908C7DE214D56119DE207" - let validFullFrontmatter = "E3742447779570EC372DD5DA9C56846F" + let validFullFrontmatter = "E2BE9000A07122842FC805530DDC9FDA" let invalidMissingMandatoryFrontmatter = "4331EE804414463D7E6DE9B8B6A3D49C" module BindingFrontmatter = let validMandatoryFrontmatter = "FC9558E6681A4114794BA912925FC283" - let validFullFrontmatter = "7996D96B4690896224B8D1D1FB621FC7" + let validFullFrontmatter = "93B48B7357D19EC9F78A6F578A47CBEC" let invalidMissingMandatoryFrontmatter = "94C704CFD2538A819CC2C0FFA406A355" module BinaryContent = @@ -154,6 +180,8 @@ module ValidationPackageMetadata = MajorVersion = 1, MinorVersion = 0, PatchVersion = 0, + PreReleaseVersionSuffix = "alpha.1", + BuildMetadataVersionSuffix = "build.1", Publish = true, Authors = [|Author.allFields|], Tags = [|OntologyAnnotation.allFields|], @@ -198,6 +226,8 @@ Name: valid MajorVersion: 2 MinorVersion: 0 PatchVersion: 0 +PreReleaseVersionSuffix: alpha.1 +BuildMetadataVersionSuffix: build.1 Summary: My package does the thing. Description: | My package does the thing. @@ -231,6 +261,8 @@ Name: valid MajorVersion: 2 MinorVersion: 0 PatchVersion: 0 +PreReleaseVersionSuffix: alpha.1 +BuildMetadataVersionSuffix: build.1 Summary: My package does the thing. Description: | My package does the thing. @@ -343,6 +375,8 @@ Name: valid MajorVersion: 2 MinorVersion: 0 PatchVersion: 0 +PreReleaseVersionSuffix: alpha.1 +BuildMetadataVersionSuffix: build.1 Summary: My package does the thing. Description: | My package does the thing. @@ -376,6 +410,8 @@ Name: valid MajorVersion: 2 MinorVersion: 0 PatchVersion: 0 +PreReleaseVersionSuffix: alpha.1 +BuildMetadataVersionSuffix: build.1 Summary: My package does the thing. Description: | My package does the thing. @@ -475,6 +511,8 @@ It does it very fast, it does it very swell. MajorVersion = 2, MinorVersion = 0, PatchVersion = 0, + PreReleaseVersionSuffix = "alpha.1", + BuildMetadataVersionSuffix = "build.1", Summary = "My package does the thing.", Publish = true, Description = """My package does the thing. diff --git a/tests/IndexTests/ValidationPackageIndexTests.fs b/tests/IndexTests/ValidationPackageIndexTests.fs index 47b78cb..759f204 100644 --- a/tests/IndexTests/ValidationPackageIndexTests.fs +++ b/tests/IndexTests/ValidationPackageIndexTests.fs @@ -9,97 +9,310 @@ open AVPRIndex.Frontmatter open Utils open ReferenceObjects -module IO = +module StaticMethods = - module CommentFrontmatter = + [] + let ``create function for mandatory fields``() = + let actual = + ValidationPackageIndex.create( + repoPath = "fixtures/Frontmatter/Comment/valid@1.0.0.fsx", + fileName = "valid@1.0.0.fsx", + lastUpdated = testDate, + contentHash = "2A29D85A29D908C7DE214D56119DE207", + metadata = ValidationPackageMetadata.create( + name = "valid", + majorVersion = 1, + minorVersion = 0, + patchVersion = 0, + summary = "My package does the thing.", + description = """My package does the thing. +It does it very good, it does it very well. +It does it very fast, it does it very swell. +""".ReplaceLineEndings("\n")) + ) + Assert.Equivalent(ValidationPackageIndex.CommentFrontmatter.validMandatoryFrontmatter, actual) + Assert.Equal(ValidationPackageIndex.CommentFrontmatter.validMandatoryFrontmatter, actual) - open System.IO + [] + let ``create function for all fields``() = + let actual = + ValidationPackageIndex.create( + repoPath = "fixtures/Frontmatter/Comment/valid@2.0.0.fsx", + fileName = "valid@2.0.0.fsx", + lastUpdated = testDate, + contentHash = "E2BE9000A07122842FC805530DDC9FDA", + metadata = ValidationPackageMetadata.create( + name = "valid", + majorVersion = 2, + minorVersion = 0, + patchVersion = 0, + summary = "My package does the thing.", + description = """My package does the thing. +It does it very good, it does it very well. +It does it very fast, it does it very swell. +""".ReplaceLineEndings("\n"), + PreReleaseVersionSuffix = "alpha.1", + BuildMetadataVersionSuffix = "build.1", + Publish = true, + Authors = [| + Author( + FullName = "John Doe", + Email = "j@d.com", + Affiliation = "University of Nowhere", + AffiliationLink = "https://nowhere.edu" + ) + Author( + FullName = "Jane Doe", + Email = "jj@d.com", + Affiliation = "University of Somewhere", + AffiliationLink = "https://somewhere.edu" + ) + |], + Tags = [| + OntologyAnnotation(Name = "validation") + OntologyAnnotation(Name = "my-tag", TermSourceREF = "my-ontology", TermAccessionNumber = "MO:12345") + |], + ReleaseNotes = """- initial release + - does the thing + - does it well +""".ReplaceLineEndings("\n"), + CQCHookEndpoint = "https://hook.com" + ) + ) + Assert.Equivalent(ValidationPackageIndex.CommentFrontmatter.validFullFrontmatter, actual) + Assert.Equal(ValidationPackageIndex.CommentFrontmatter.validFullFrontmatter, actual) - [] - let ``valid indexed package is extracted from valid mandatory field test file`` () = + [] + let ``tryGetSemanticVersion from valid package with mandatory fields``() = + let actual = ValidationPackageIndex.CommentFrontmatter.validMandatoryFrontmatter |> ValidationPackageIndex.tryGetSemanticVersion + Assert.True(actual.IsSome) + Assert.Equivalent(SemVer.SemVers.mandatory, actual.Value) + Assert.Equal(SemVer.SemVers.mandatory, actual.Value) - let actual = - ValidationPackageIndex.create( - repoPath = "fixtures/Frontmatter/Comment/valid@1.0.0.fsx", - lastUpdated = testDate - ) - Assert.Equivalent(ValidationPackageIndex.CommentFrontmatter.validMandatoryFrontmatter, actual) + [] + let ``getSemanticVersion from valid package with mandatory fields``() = + let actual = ValidationPackageIndex.CommentFrontmatter.validMandatoryFrontmatter |> ValidationPackageIndex.getSemanticVersion + Assert.Equivalent(SemVer.SemVers.mandatory, actual) + Assert.Equal(SemVer.SemVers.mandatory, actual) + [] + let ``tryGetSemanticVersionString from valid package with mandatory fields``() = + let actual = ValidationPackageIndex.CommentFrontmatter.validMandatoryFrontmatter |> ValidationPackageIndex.tryGetSemanticVersionString + Assert.True(actual.IsSome) + Assert.Equal(SemVer.Strings.mandatory, actual.Value) - [] - let ``valid indexed package is extracted from all fields test file`` () = + [] + let ``getSemanticVersionString from valid package with mandatory fields``() = + let actual = ValidationPackageIndex.CommentFrontmatter.validMandatoryFrontmatter |> ValidationPackageIndex.getSemanticVersionString + Assert.Equal(SemVer.Strings.mandatory, actual) - let actual = - ValidationPackageIndex.create( - repoPath = "fixtures/Frontmatter/Comment/valid@2.0.0.fsx", - lastUpdated = testDate - ) - Assert.Equivalent(ValidationPackageIndex.CommentFrontmatter.validFullFrontmatter, actual) + [] + let ``tryGetSemanticVersion from valid package with all fields``() = + let actual = ValidationPackageIndex.CommentFrontmatter.validFullFrontmatter |> ValidationPackageIndex.tryGetSemanticVersion + Assert.True(actual.IsSome) + Assert.Equivalent(SemVer.SemVers.fixtureFile, actual.Value) + Assert.Equal(SemVer.SemVers.fixtureFile, actual.Value) - [] - let ``invalid indexed package is extracted from testfile with missing fields`` () = + [] + let ``getSemanticVersion from valid package with all fields``() = + let actual = ValidationPackageIndex.CommentFrontmatter.validFullFrontmatter |> ValidationPackageIndex.getSemanticVersion + Assert.Equivalent(SemVer.SemVers.fixtureFile, actual) + Assert.Equal(SemVer.SemVers.fixtureFile, actual) - let actual = - ValidationPackageIndex.create( - repoPath = "fixtures/Frontmatter/Comment/invalid@0.0.fsx", - lastUpdated = testDate - ) - Assert.Equivalent(ValidationPackageIndex.CommentFrontmatter.invalidMissingMandatoryFrontmatter, actual) - - [] - let ``CRLF: correct content hash (with line endings replaced) is extracted from valid mandatory field test file`` () = - let tmp_path = Path.GetTempFileName() - File.WriteAllText( - tmp_path, - Frontmatter.Comment.validMandatoryFrontmatter.ReplaceLineEndings("\r\n") + [] + let ``tryGetSemanticVersionString from valid package with all fields``() = + let actual = ValidationPackageIndex.CommentFrontmatter.validFullFrontmatter |> ValidationPackageIndex.tryGetSemanticVersionString + Assert.True(actual.IsSome) + Assert.Equal(SemVer.Strings.fixtureFile, actual.Value) + + [] + let ``getSemanticVersionString from valid package with all fields``() = + let actual = ValidationPackageIndex.CommentFrontmatter.validFullFrontmatter |> ValidationPackageIndex.getSemanticVersionString + Assert.Equal(SemVer.Strings.fixtureFile, actual) + +module CommentFrontmatterIO = + + open System.IO + + [] + let ``valid indexed package is extracted from valid mandatory field test file`` () = + + let actual = + ValidationPackageIndex.create( + repoPath = "fixtures/Frontmatter/Comment/valid@1.0.0.fsx", + lastUpdated = testDate ) - let actual = - ValidationPackageIndex.create( - repoPath = tmp_path, - lastUpdated = testDate - ) - let expected = { - ValidationPackageIndex.CommentFrontmatter.validMandatoryFrontmatter with - RepoPath = tmp_path - FileName = Path.GetFileName(tmp_path) - } - Assert.Equivalent(expected, actual) - - - [] - let ``CRLF: correct content hash (with line endings replaced) is extracted from all fields test file`` () = - let tmp_path = Path.GetTempFileName() - File.WriteAllText( - tmp_path, - Frontmatter.Comment.validFullFrontmatter.ReplaceLineEndings("\r\n") + Assert.Equivalent(ValidationPackageIndex.CommentFrontmatter.validMandatoryFrontmatter, actual) + + + [] + let ``valid indexed package is extracted from all fields test file`` () = + + let actual = + ValidationPackageIndex.create( + repoPath = "fixtures/Frontmatter/Comment/valid@2.0.0.fsx", + lastUpdated = testDate ) - let actual = - ValidationPackageIndex.create( - repoPath = tmp_path, - lastUpdated = testDate - ) - let expected = { - ValidationPackageIndex.CommentFrontmatter.validFullFrontmatter with - RepoPath = tmp_path - FileName = Path.GetFileName(tmp_path) - } - Assert.Equivalent(expected, actual) - - [] - let ``CRLF: correct content hash (with line endings replaced) is extracted from testfile with missing fields`` () = - let tmp_path = Path.GetTempFileName() - File.WriteAllText( - tmp_path, - Frontmatter.Comment.invalidMissingMandatoryFrontmatter.ReplaceLineEndings("\r\n") + Assert.Equivalent(ValidationPackageIndex.CommentFrontmatter.validFullFrontmatter, actual) + + [] + let ``invalid indexed package is extracted from testfile with missing fields`` () = + + let actual = + ValidationPackageIndex.create( + repoPath = "fixtures/Frontmatter/Comment/invalid@0.0.fsx", + lastUpdated = testDate ) - let actual = - ValidationPackageIndex.create( - repoPath = tmp_path, - lastUpdated = testDate - ) - let expected = { - ValidationPackageIndex.CommentFrontmatter.invalidMissingMandatoryFrontmatter with - RepoPath = tmp_path - FileName = Path.GetFileName(tmp_path) - } - Assert.Equivalent(expected, actual) \ No newline at end of file + Assert.Equivalent(ValidationPackageIndex.CommentFrontmatter.invalidMissingMandatoryFrontmatter, actual) + + [] + let ``CRLF: correct content hash (with line endings replaced) is extracted from valid mandatory field test file`` () = + let tmp_path = Path.GetTempFileName() + File.WriteAllText( + tmp_path, + Frontmatter.Comment.validMandatoryFrontmatter.ReplaceLineEndings("\r\n") + ) + let actual = + ValidationPackageIndex.create( + repoPath = tmp_path, + lastUpdated = testDate + ) + let expected = { + ValidationPackageIndex.CommentFrontmatter.validMandatoryFrontmatter with + RepoPath = tmp_path + FileName = Path.GetFileName(tmp_path) + } + Assert.Equivalent(expected, actual) + + + [] + let ``CRLF: correct content hash (with line endings replaced) is extracted from all fields test file`` () = + let tmp_path = Path.GetTempFileName() + File.WriteAllText( + tmp_path, + Frontmatter.Comment.validFullFrontmatter.ReplaceLineEndings("\r\n") + ) + let actual = + ValidationPackageIndex.create( + repoPath = tmp_path, + lastUpdated = testDate + ) + let expected = { + ValidationPackageIndex.CommentFrontmatter.validFullFrontmatter with + RepoPath = tmp_path + FileName = Path.GetFileName(tmp_path) + } + Assert.Equivalent(expected, actual) + + [] + let ``CRLF: correct content hash (with line endings replaced) is extracted from testfile with missing fields`` () = + let tmp_path = Path.GetTempFileName() + File.WriteAllText( + tmp_path, + Frontmatter.Comment.invalidMissingMandatoryFrontmatter.ReplaceLineEndings("\r\n") + ) + let actual = + ValidationPackageIndex.create( + repoPath = tmp_path, + lastUpdated = testDate + ) + let expected = { + ValidationPackageIndex.CommentFrontmatter.invalidMissingMandatoryFrontmatter with + RepoPath = tmp_path + FileName = Path.GetFileName(tmp_path) + } + Assert.Equivalent(expected, actual) + + +module BindingFrontmatterIO = + + open System.IO + + [] + let ``valid indexed package is extracted from valid mandatory field test file`` () = + + let actual = + ValidationPackageIndex.create( + repoPath = "fixtures/Frontmatter/Binding/valid@1.0.0.fsx", + lastUpdated = testDate + ) + Assert.Equivalent(ValidationPackageIndex.BindingFrontmatter.validMandatoryFrontmatter, actual) + + + [] + let ``valid indexed package is extracted from all fields test file`` () = + + let actual = + ValidationPackageIndex.create( + repoPath = "fixtures/Frontmatter/Binding/valid@2.0.0.fsx", + lastUpdated = testDate + ) + Assert.Equivalent(ValidationPackageIndex.BindingFrontmatter.validFullFrontmatter, actual) + + [] + let ``invalid indexed package is extracted from testfile with missing fields`` () = + + let actual = + ValidationPackageIndex.create( + repoPath = "fixtures/Frontmatter/Binding/invalid@0.0.fsx", + lastUpdated = testDate + ) + Assert.Equivalent(ValidationPackageIndex.BindingFrontmatter.invalidMissingMandatoryFrontmatter, actual) + + [] + let ``CRLF: correct content hash (with line endings replaced) is extracted from valid mandatory field test file`` () = + let tmp_path = Path.GetTempFileName() + File.WriteAllText( + tmp_path, + Frontmatter.Binding.validMandatoryFrontmatter.ReplaceLineEndings("\r\n") + ) + let actual = + ValidationPackageIndex.create( + repoPath = tmp_path, + lastUpdated = testDate + ) + let expected = { + ValidationPackageIndex.BindingFrontmatter.validMandatoryFrontmatter with + RepoPath = tmp_path + FileName = Path.GetFileName(tmp_path) + } + Assert.Equivalent(expected, actual) + + + [] + let ``CRLF: correct content hash (with line endings replaced) is extracted from all fields test file`` () = + let tmp_path = Path.GetTempFileName() + File.WriteAllText( + tmp_path, + Frontmatter.Binding.validFullFrontmatter.ReplaceLineEndings("\r\n") + ) + let actual = + ValidationPackageIndex.create( + repoPath = tmp_path, + lastUpdated = testDate + ) + let expected = { + ValidationPackageIndex.BindingFrontmatter.validFullFrontmatter with + RepoPath = tmp_path + FileName = Path.GetFileName(tmp_path) + } + Assert.Equivalent(expected, actual) + + [] + let ``CRLF: correct content hash (with line endings replaced) is extracted from testfile with missing fields`` () = + let tmp_path = Path.GetTempFileName() + File.WriteAllText( + tmp_path, + Frontmatter.Binding.invalidMissingMandatoryFrontmatter.ReplaceLineEndings("\r\n") + ) + let actual = + ValidationPackageIndex.create( + repoPath = tmp_path, + lastUpdated = testDate + ) + let expected = { + ValidationPackageIndex.BindingFrontmatter.invalidMissingMandatoryFrontmatter with + RepoPath = tmp_path + FileName = Path.GetFileName(tmp_path) + } + Assert.Equivalent(expected, actual) \ No newline at end of file diff --git a/tests/IndexTests/fixtures/Frontmatter/Binding/valid@2.0.0.fsx b/tests/IndexTests/fixtures/Frontmatter/Binding/valid@2.0.0.fsx index f6f3b01..168ef51 100644 --- a/tests/IndexTests/fixtures/Frontmatter/Binding/valid@2.0.0.fsx +++ b/tests/IndexTests/fixtures/Frontmatter/Binding/valid@2.0.0.fsx @@ -4,6 +4,8 @@ Name: valid MajorVersion: 2 MinorVersion: 0 PatchVersion: 0 +PreReleaseVersionSuffix: alpha.1 +BuildMetadataVersionSuffix: build.1 Summary: My package does the thing. Description: | My package does the thing. diff --git a/tests/IndexTests/fixtures/Frontmatter/Comment/valid@2.0.0.fsx b/tests/IndexTests/fixtures/Frontmatter/Comment/valid@2.0.0.fsx index fc3c074..8dbcb90 100644 --- a/tests/IndexTests/fixtures/Frontmatter/Comment/valid@2.0.0.fsx +++ b/tests/IndexTests/fixtures/Frontmatter/Comment/valid@2.0.0.fsx @@ -4,6 +4,8 @@ Name: valid MajorVersion: 2 MinorVersion: 0 PatchVersion: 0 +PreReleaseVersionSuffix: alpha.1 +BuildMetadataVersionSuffix: build.1 Summary: My package does the thing. Description: | My package does the thing.