diff --git a/ARCtrl.sln b/ARCtrl.sln index 15f051fb..82ac26ff 100644 --- a/ARCtrl.sln +++ b/ARCtrl.sln @@ -76,6 +76,12 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "ARCtrl.ValidationPackages", EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "ARCtrl.Yaml", "src\Yaml\ARCtrl.Yaml.fsproj", "{4CC3AAC2-030B-4B2E-A386-9C1F68E42238}" EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "ARCtrl.ValidationPackages.Tests", "tests\ValidationPackages\ARCtrl.ValidationPackages.Tests.fsproj", "{1CA11165-4B70-41D2-A846-50374E85385E}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "ARCtrl.Yaml.Tests", "tests\Yaml\ARCtrl.Yaml.Tests.fsproj", "{5810EF87-4F85-4B4C-98E3-833AE914C628}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "ARCtrl.Contract.Tests", "tests\Contract\ARCtrl.Contract.Tests.fsproj", "{D10D12C7-B877-423B-867D-161D99E673C9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -150,6 +156,18 @@ Global {4CC3AAC2-030B-4B2E-A386-9C1F68E42238}.Debug|Any CPU.Build.0 = Debug|Any CPU {4CC3AAC2-030B-4B2E-A386-9C1F68E42238}.Release|Any CPU.ActiveCfg = Release|Any CPU {4CC3AAC2-030B-4B2E-A386-9C1F68E42238}.Release|Any CPU.Build.0 = Release|Any CPU + {1CA11165-4B70-41D2-A846-50374E85385E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1CA11165-4B70-41D2-A846-50374E85385E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1CA11165-4B70-41D2-A846-50374E85385E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1CA11165-4B70-41D2-A846-50374E85385E}.Release|Any CPU.Build.0 = Release|Any CPU + {5810EF87-4F85-4B4C-98E3-833AE914C628}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5810EF87-4F85-4B4C-98E3-833AE914C628}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5810EF87-4F85-4B4C-98E3-833AE914C628}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5810EF87-4F85-4B4C-98E3-833AE914C628}.Release|Any CPU.Build.0 = Release|Any CPU + {D10D12C7-B877-423B-867D-161D99E673C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D10D12C7-B877-423B-867D-161D99E673C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D10D12C7-B877-423B-867D-161D99E673C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D10D12C7-B877-423B-867D-161D99E673C9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -173,6 +191,9 @@ Global {501F6D1E-6300-4CA4-8E61-3523BCF4D533} = {64B34A6E-318D-4E6E-9262-CE52C9B85A38} {0C35D768-BF55-4BD9-B915-35125CED65A0} = {6DA2330B-D407-4FB1-AF05-B0184034EC44} {4CC3AAC2-030B-4B2E-A386-9C1F68E42238} = {6DA2330B-D407-4FB1-AF05-B0184034EC44} + {1CA11165-4B70-41D2-A846-50374E85385E} = {64B34A6E-318D-4E6E-9262-CE52C9B85A38} + {5810EF87-4F85-4B4C-98E3-833AE914C628} = {64B34A6E-318D-4E6E-9262-CE52C9B85A38} + {D10D12C7-B877-423B-867D-161D99E673C9} = {64B34A6E-318D-4E6E-9262-CE52C9B85A38} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1E354DE6-99BA-421E-9EF8-E808B855A85F} diff --git a/build/ProjectInfo.fs b/build/ProjectInfo.fs index 128cf543..c74d1f2e 100644 --- a/build/ProjectInfo.fs +++ b/build/ProjectInfo.fs @@ -1,4 +1,4 @@ -module ProjectInfo +module ProjectInfo open Fake.Core open Helpers @@ -13,6 +13,9 @@ let testProjects = "tests/Spreadsheet" "tests/FileSystem" "tests/ARCtrl" + "tests/Yaml" + "tests/ValidationPackages" + "tests/Contract" ] /// Native JS test paths diff --git a/src/ARCtrl/ARC.fs b/src/ARCtrl/ARC.fs index 95411f4b..6687e4df 100644 --- a/src/ARCtrl/ARC.fs +++ b/src/ARCtrl/ARC.fs @@ -1,5 +1,6 @@ namespace ARCtrl +open ARCtrl.ValidationPackages open ARCtrl.FileSystem open ARCtrl.Contract open ARCtrl @@ -60,7 +61,8 @@ module ARCAux = let tree = FileSystemTree.createRootFolder [|workflows;runs|] |> FileSystem.create - fs.Union(tree) + fs.Union(tree) + [] type ARC(?isa : ArcInvestigation, ?cwl : CWL.CWL, ?fs : FileSystem.FileSystem) = @@ -570,6 +572,46 @@ type ARC(?isa : ArcInvestigation, ?cwl : CWL.CWL, ?fs : FileSystem.FileSystem) = ARCtrl.Json.ARC.ROCrate.encoder (Option.get obj.ISA) |> ARCtrl.Json.Encode.toJsonString (ARCtrl.Json.Encode.defaultSpaces spaces) + /// + /// Returns the write contract for the input ValidationPackagesConfig object. + /// + /// This will mutate the ARC file system to include the `.arc/validation_packages.yml` file if it is not already included. + /// + /// the config to write + member this.GetValidationPackagesConfigWriteContract(vpc: ValidationPackagesConfig) = + let paths = this.FileSystem.Tree.ToFilePaths() + if not (Array.contains ValidationPackagesConfigHelper.ConfigFilePath paths) then + Array.append [|ValidationPackagesConfigHelper.ConfigFilePath|] paths + |> this.SetFilePaths + ValidationPackagesConfig.toCreateContract vpc + + /// + /// Returns the delete contract for `.arc/validation_packages.yml` + /// + /// If the ARC file system includes the `.arc/validation_packages.yml` file, it is removed. + /// + /// + member this.GetValidationPackagesConfigDeleteContract(vpc) = + let paths = this.FileSystem.Tree.ToFilePaths() + if (Array.contains ValidationPackagesConfigHelper.ConfigFilePath paths) then + paths + |> Array.filter (fun p -> not (p = ValidationPackagesConfigHelper.ConfigFilePath)) + |> this.SetFilePaths + ValidationPackagesConfig.toDeleteContract vpc + + /// + /// Returns the read contract for `.arc/validation_packages.yml` + /// + member this.GetValidationPackagesConfigReadContract() = + ValidationPackagesConfigHelper.ReadContract + + /// + /// Returns the ValidationPackagesConfig object from the given read contract if possible, otherwise returns None/null. + /// + /// the input contract that contains the config in it's DTO + member this.GetValidationPackagesConfigFromReadContract(contract) = + ValidationPackagesConfig.tryFromReadContract contract + //-Pseudo code-// //// Option 1 //let fs, readcontracts = ARC.FSFromFilePaths filepaths diff --git a/src/Contract/ValidationPackagesConfig.fs b/src/Contract/ValidationPackagesConfig.fs index 67ae6b58..d4126775 100644 --- a/src/Contract/ValidationPackagesConfig.fs +++ b/src/Contract/ValidationPackagesConfig.fs @@ -1,34 +1,35 @@ namespace ARCtrl.Contract open ARCtrl.FileSystem -open ARCtrl.ArcPathHelper open ARCtrl open ARCtrl.Yaml open ARCtrl.Helper open ARCtrl.ValidationPackages +module ValidationPackagesConfigHelper = + + let ConfigFilePath = [|ArcPathHelper.ARCConfigFolderName; ArcPathHelper.ValidationPackagesYamlFileName|] |> ArcPathHelper.combineMany + + let ReadContract : Contract = {Operation = READ; DTOType = Some DTOType.YAML; Path = ConfigFilePath; DTO = None} + + [] module ValidationPackagesConfigExtensions = let (|ValidationPackagesYamlPath|_|) (input) = match input with - | [|ARCConfigFolderName; ValidationPackagesYamlFileName|] -> - let path = ARCtrl.ArcPathHelper.combineMany input + | [|ArcPathHelper.ARCConfigFolderName; ArcPathHelper.ValidationPackagesYamlFileName|] -> + let path = ArcPathHelper.combineMany input Some path | _ -> None - let internal config_file_path = [|ARCConfigFolderName; ValidationPackagesYamlFileName|] |> ARCtrl.ArcPathHelper.combineMany - type ValidationPackagesConfig with member this.ToCreateContract () = - Contract.createCreate(config_file_path, DTOType.YAML, DTO.Text (this |> ValidationPackagesConfig.toYamlString())) - - member this.ToUpdateContract () = - Contract.createUpdate(config_file_path, DTOType.YAML, DTO.Text (this |> ValidationPackagesConfig.toYamlString())) + Contract.createCreate(ValidationPackagesConfigHelper.ConfigFilePath, DTOType.YAML, DTO.Text (this |> ValidationPackagesConfig.toYamlString())) member this.ToDeleteContract () = - Contract.createDelete(config_file_path) + Contract.createDelete(ValidationPackagesConfigHelper.ConfigFilePath) static member toDeleteContract (config: ValidationPackagesConfig) : Contract = config.ToDeleteContract() @@ -36,12 +37,9 @@ module ValidationPackagesConfigExtensions = static member toCreateContract (config: ValidationPackagesConfig) : Contract = config.ToCreateContract() - static member toUpdateContract (config: ValidationPackagesConfig) : Contract = - config.ToUpdateContract() - static member tryFromReadContract (c:Contract) = match c with - | {Operation = READ; DTOType = Some DTOType.YAML; DTO = Some (DTO.Text yaml)} -> + | {Operation = READ; DTOType = Some DTOType.YAML; Path = p; DTO = Some (DTO.Text yaml)} when p = ValidationPackagesConfigHelper.ConfigFilePath -> yaml |> ValidationPackagesConfig.fromYamlString |> Some diff --git a/src/ValidationPackages/ValidationPackage.fs b/src/ValidationPackages/ValidationPackage.fs index 726ebf7c..b36e6a9e 100644 --- a/src/ValidationPackages/ValidationPackage.fs +++ b/src/ValidationPackages/ValidationPackage.fs @@ -1,4 +1,4 @@ -namespace ARCtrl.ValidationPackages +namespace ARCtrl.ValidationPackages open ARCtrl.Helper open Fable.Core @@ -22,6 +22,16 @@ type ValidationPackage(name, ?version) = member this.Copy() = ValidationPackage.make this.Name this.Version + /// Pretty printer + override this.ToString() = + [ + "{" + $" Name = {this.Name}" + if version.IsSome then $" Version = {this.Version.Value}" + "}" + ] + |> String.concat System.Environment.NewLine + override this.Equals(obj) = match obj with | :? ValidationPackage as other_vp -> other_vp.Name = this.Name && other_vp.Version = this.Version diff --git a/src/ValidationPackages/ValidationPackagesConfig.fs b/src/ValidationPackages/ValidationPackagesConfig.fs index 1b7111a9..94e0dc6b 100644 --- a/src/ValidationPackages/ValidationPackagesConfig.fs +++ b/src/ValidationPackages/ValidationPackagesConfig.fs @@ -1,4 +1,4 @@ -namespace ARCtrl.ValidationPackages +namespace ARCtrl.ValidationPackages open ARCtrl.Helper open Fable.Core @@ -6,8 +6,8 @@ open Fable.Core [] type ValidationPackagesConfig(validation_packages, ?arc_specification) = - let mutable _validation_packages : ResizeArray = validation_packages let mutable _arc_specification : string option = arc_specification + let mutable _validation_packages : ResizeArray = validation_packages member this.ValidationPackages with get() = _validation_packages @@ -22,15 +22,39 @@ type ValidationPackagesConfig(validation_packages, ?arc_specification) = member this.Copy() = ValidationPackagesConfig.make this.ValidationPackages this.ARCSpecification - override this.Equals(obj) = - match obj with - | :? ValidationPackagesConfig as other_vpc -> other_vpc.ValidationPackages = this.ValidationPackages && other_vpc.ARCSpecification = this.ARCSpecification + + /// Pretty printer + override this.ToString() = + [ + "{" + if this.ARCSpecification.IsSome then $" ARCSpecification = {this.ARCSpecification.Value}" + " ValidationPackages = [" + this.ValidationPackages + |> Seq.map (fun vp -> vp.ToString()) + |> String.concat $";{System.Environment.NewLine}" + "]" + "}" + ] + |> String.concat System.Environment.NewLine + + member this.StructurallyEquals (other: ValidationPackagesConfig) = + let sort = Array.ofSeq >> Array.sortBy (fun (vp: ValidationPackage) -> vp.Name, vp.Version) + let specs = this.ARCSpecification = other.ARCSpecification + let packages = Seq.compare (sort this.ValidationPackages) (sort other.ValidationPackages) + specs && packages + + member this.ReferenceEquals (other: ValidationPackagesConfig) = System.Object.ReferenceEquals(this,other) + + override this.Equals other = + match other with + | :? ValidationPackagesConfig as other_vp -> + this.StructurallyEquals(other_vp) | _ -> false override this.GetHashCode() = [| - this.ValidationPackages.GetHashCode() |> box HashCodes.boxHashOption this.ARCSpecification + this.ValidationPackages |> HashCodes.boxHashSeq |] |> HashCodes.boxHashArray |> fun x -> x :?> int \ No newline at end of file diff --git a/src/Yaml/Decode.fs b/src/Yaml/Decode.fs index e47d8377..377a1b6f 100644 --- a/src/Yaml/Decode.fs +++ b/src/Yaml/Decode.fs @@ -1,33 +1,7 @@ -namespace Arctrl.Yaml +namespace ARCtrl.Yaml module Decode = - // yamlicious equivalents for this? - - //let helpers = - // #if FABLE_COMPILER_PYTHON - // Thoth.Json.Python.Decode.helpers - // #endif - // #if FABLE_COMPILER_JAVASCRIPT - // Thoth.Json.JavaScript.Decode.helpers - // #endif - // #if !FABLE_COMPILER - // Thoth.Json.Newtonsoft.Decode.helpers - // #endif - - //let inline fromJsonString (decoder : Decoder<'a>) (s : string) : 'a = - // #if FABLE_COMPILER_PYTHON - // match Thoth.Json.Python.Decode.fromString decoder s with - // #endif - // #if FABLE_COMPILER_JAVASCRIPT - // match Thoth.Json.JavaScript.Decode.fromString decoder s with - // #endif - // #if !FABLE_COMPILER - // match Thoth.Json.Newtonsoft.Decode.fromString decoder s with - // #endif - // | Ok a -> a - // | Error e -> failwith (sprintf "Error decoding string: %O" e) - open YAMLicious open YAMLicious.YAMLiciousTypes open YAMLicious.Reader diff --git a/src/Yaml/Encode.fs b/src/Yaml/Encode.fs index 4a7d8f2d..55bd0e2b 100644 --- a/src/Yaml/Encode.fs +++ b/src/Yaml/Encode.fs @@ -1,4 +1,4 @@ -namespace Arctrl.Yaml +namespace ARCtrl.Yaml module Encode = diff --git a/src/Yaml/ValidationPackage.fs b/src/Yaml/ValidationPackage.fs index c4c64fb0..1d82c319 100644 --- a/src/Yaml/ValidationPackage.fs +++ b/src/Yaml/ValidationPackage.fs @@ -1,4 +1,4 @@ -namespace ARCtrl.Yaml +namespace ARCtrl.Yaml open ARCtrl.ValidationPackages open YAMLicious @@ -6,10 +6,13 @@ open YAMLicious.YAMLiciousTypes module ValidationPackage = + let [] NAME_KEY = "name" + let [] VERSION_KEY = "version" + let encoder (validationpackage : ValidationPackage) = [ - "name", Encode.string validationpackage.Name - Encode.tryInclude "version" Encode.string (validationpackage.Version) + NAME_KEY, Encode.string validationpackage.Name + Encode.tryInclude VERSION_KEY Encode.string (validationpackage.Version) ] |> Encode.choose |> Encode.object @@ -17,15 +20,15 @@ module ValidationPackage = let decoder : (YAMLElement -> ValidationPackage) = Decode.object (fun get -> ValidationPackage( - name = get.Required.Field "name" Decode.string, - ?version = get.Optional.Field "version" Decode.string + name = get.Required.Field NAME_KEY Decode.string, + ?version = get.Optional.Field VERSION_KEY Decode.string ) ) [] module ValidationPackageExtensions = - open Arctrl.Yaml + open ARCtrl.Yaml type ValidationPackage with static member fromYamlString (s:string) = diff --git a/src/Yaml/ValidationPackagesConfig.fs b/src/Yaml/ValidationPackagesConfig.fs index 5d453f5b..90a08719 100644 --- a/src/Yaml/ValidationPackagesConfig.fs +++ b/src/Yaml/ValidationPackagesConfig.fs @@ -1,4 +1,4 @@ -namespace ARCtrl.Yaml +namespace ARCtrl.Yaml open ARCtrl.ValidationPackages open YAMLicious @@ -6,10 +6,13 @@ open YAMLicious.YAMLiciousTypes module ValidationPackagesConfig = + let [] ARC_SPECIFICATION_KEY = "arc_specification" + let [] VALIDATION_PACKAGES_KEY = "validation_packages" + let encoder (validationpackage : ValidationPackagesConfig) = [ - "validation_packages", Encode.resizearray ValidationPackage.encoder validationpackage.ValidationPackages - Encode.tryInclude "arc_specification" Encode.string (validationpackage.ARCSpecification) + Encode.tryInclude ARC_SPECIFICATION_KEY Encode.string (validationpackage.ARCSpecification) + VALIDATION_PACKAGES_KEY, Encode.resizearray ValidationPackage.encoder validationpackage.ValidationPackages ] |> Encode.choose |> Encode.object @@ -17,15 +20,15 @@ module ValidationPackagesConfig = let decoder : (YAMLElement -> ValidationPackagesConfig) = Decode.object (fun get -> ValidationPackagesConfig( - validation_packages = get.Required.Field "validation_packages" (Decode.resizearray ValidationPackage.decoder), - ?arc_specification = get.Optional.Field "arc_specification" Decode.string + validation_packages = get.Required.Field VALIDATION_PACKAGES_KEY (Decode.resizearray ValidationPackage.decoder), + ?arc_specification = get.Optional.Field ARC_SPECIFICATION_KEY Decode.string ) ) [] module ValidationPackageConfigExtensions = - open Arctrl.Yaml + open ARCtrl.Yaml type ValidationPackagesConfig with static member fromYamlString (s:string) = diff --git a/tests/ARCtrl/ARCtrl.Tests.fsproj b/tests/ARCtrl/ARCtrl.Tests.fsproj index fe3200a9..bfab53f6 100644 --- a/tests/ARCtrl/ARCtrl.Tests.fsproj +++ b/tests/ARCtrl/ARCtrl.Tests.fsproj @@ -11,6 +11,7 @@ + diff --git a/tests/ARCtrl/Main.fs b/tests/ARCtrl/Main.fs index 6f7cfce1..9f70b9ac 100644 --- a/tests/ARCtrl/Main.fs +++ b/tests/ARCtrl/Main.fs @@ -1,4 +1,4 @@ -module Main.Tests +module Main.Tests open Fable.Pyxpecto @@ -7,6 +7,7 @@ let all = testSequenced <| testList "ARCtrl" [ ARCtrl.WebRequest.Tests.main ARCtrl.SemVer.Tests.main ARCtrl.Template.Tests.main + ARCtrl.ValidationPackagesConfig.Tests.main ARCtrl.Tests.main ] diff --git a/tests/ARCtrl/ValidationPackagesConfig.Tests.fs b/tests/ARCtrl/ValidationPackagesConfig.Tests.fs new file mode 100644 index 00000000..7c6f0214 --- /dev/null +++ b/tests/ARCtrl/ValidationPackagesConfig.Tests.fs @@ -0,0 +1,67 @@ +module ARCtrl.ValidationPackagesConfig.Tests + +open TestingUtils +open ARCtrl +open ARCtrl.ValidationPackages +open ARCtrl.Yaml +open ARCtrl.Contract + +let vpc_toplevel_api_tests = testList "ARC() ValidationPackages top level API" [ + let vpc = ValidationPackages.ValidationPackagesConfig(new ResizeArray([ValidationPackage("name", "version")]), "arc_specification") + + testCase "GetValidationPackagesConfigWriteContract" <| fun _ -> + let arc = ARC() + let contract = arc.GetValidationPackagesConfigWriteContract(vpc) + Expect.equal contract.Operation Operation.CREATE "" + Expect.equal contract.Path ValidationPackagesConfigHelper.ConfigFilePath "" + Expect.equal contract.DTOType (Some DTOType.YAML) "" + Expect.equal contract.DTO (Some (DTO.Text (vpc |> ValidationPackagesConfig.toYamlString()))) "" + + testCase "GetValidationPackagesConfigWriteContract adds file entry" <| fun _ -> + let arc = ARC() + let paths = arc.FileSystem.Tree.ToFilePaths() + Expect.isFalse (paths |> Seq.contains ValidationPackagesConfigHelper.ConfigFilePath) "" + let _ = arc.GetValidationPackagesConfigWriteContract(vpc) + let paths = arc.FileSystem.Tree.ToFilePaths() + Expect.isTrue (paths |> Seq.contains ValidationPackagesConfigHelper.ConfigFilePath) "" + Expect.containsAll paths [ValidationPackagesConfigHelper.ConfigFilePath] "" + + testCase "GetValidationPackagesConfigDeleteContract" <| fun _ -> + let arc = ARC() + let contract = arc.GetValidationPackagesConfigDeleteContract(vpc) + Expect.equal contract.Operation Operation.DELETE "" + Expect.equal contract.Path ValidationPackagesConfigHelper.ConfigFilePath "" + Expect.equal contract.DTOType None "" + Expect.equal contract.DTO None "" + + testCase "GetValidationPackagesConfigDeleteContract removes file entry" <| fun _ -> + let arc = ARC() + arc.FileSystem <- arc.FileSystem.AddFile(ValidationPackagesConfigHelper.ConfigFilePath) + Expect.isTrue (arc.FileSystem.Tree.ToFilePaths() |> Seq.contains ValidationPackagesConfigHelper.ConfigFilePath) "" + let _ = arc.GetValidationPackagesConfigDeleteContract(vpc) + Expect.isFalse (arc.FileSystem.Tree.ToFilePaths() |> Seq.contains ValidationPackagesConfigHelper.ConfigFilePath) "" + + + testCase "GetValidationPackagesConfigReadContract" <| fun _ -> + let arc = ARC() + let contract = arc.GetValidationPackagesConfigReadContract() + Expect.equal contract.Operation Operation.READ "" + Expect.equal contract.Path ValidationPackagesConfigHelper.ConfigFilePath "" + Expect.equal contract.DTOType (Some DTOType.YAML) "" + Expect.equal contract.DTO None "" + + testCase "GetValidationPackagesConfigFromReadContract" <| fun _ -> + let arc = ARC() + let contract = { + Operation = READ + DTOType = Some DTOType.YAML + Path = ValidationPackagesConfigHelper.ConfigFilePath + DTO = Some (DTO.Text (ValidationPackagesConfig.toYamlString() vpc)) + } + let result = arc.GetValidationPackagesConfigFromReadContract contract + Expect.equal result (Some vpc) "" +] + +let main = testList "ValidationPackagesConfig" [ + vpc_toplevel_api_tests +] \ No newline at end of file diff --git a/tests/Contract/ARCtrl.Contract.Tests.fsproj b/tests/Contract/ARCtrl.Contract.Tests.fsproj new file mode 100644 index 00000000..20bf61dd --- /dev/null +++ b/tests/Contract/ARCtrl.Contract.Tests.fsproj @@ -0,0 +1,16 @@ + + + + Exe + net8.0 + false + + + + + + + + + + \ No newline at end of file diff --git a/tests/Contract/Main.fs b/tests/Contract/Main.fs new file mode 100644 index 00000000..977fac32 --- /dev/null +++ b/tests/Contract/Main.fs @@ -0,0 +1,10 @@ +module ARCtrl.FileSystem.Tests + +open Fable.Pyxpecto + +let all = testSequenced <| testList "ValidationPackages" [ + Tests.ValidationPackagesConfig.main +] + +[] +let main argv = Pyxpecto.runTests [||] all diff --git a/tests/Contract/ValidationPackagesConfig.Tests.fs b/tests/Contract/ValidationPackagesConfig.Tests.fs new file mode 100644 index 00000000..3fbc48a4 --- /dev/null +++ b/tests/Contract/ValidationPackagesConfig.Tests.fs @@ -0,0 +1,55 @@ +module Tests.ValidationPackagesConfig + +open TestingUtils + +open ARCtrl +open ARCtrl.Yaml +open ARCtrl.Contract +open ARCtrl.ValidationPackages +open ARCtrl.Contract.ValidationPackagesConfigExtensions + +let vpc = ValidationPackages.ValidationPackagesConfig(new ResizeArray([ValidationPackage("name", "version")]), "arc_specification") + +let extension_methods_tests = testList "Extension methods" [ + testCase "ToCreateContract" <| fun _ -> + let contract = vpc.ToCreateContract() + Expect.equal contract.Operation Operation.CREATE "" + Expect.equal contract.Path ValidationPackagesConfigHelper.ConfigFilePath "" + Expect.equal contract.DTOType (Some DTOType.YAML) "" + Expect.equal contract.DTO (Some (DTO.Text (vpc |> ValidationPackagesConfig.toYamlString()))) "" + + testCase "ToDeleteContract" <| fun _ -> + let contract = vpc.ToDeleteContract() + Expect.equal contract.Operation Operation.DELETE "" + Expect.equal contract.Path ValidationPackagesConfigHelper.ConfigFilePath "" + Expect.equal contract.DTOType None "" + Expect.equal contract.DTO None "" + + testCase "toCreateContract" <| fun _ -> + let contract = ValidationPackagesConfig.toCreateContract vpc + Expect.equal contract.Operation Operation.CREATE "" + Expect.equal contract.Path ValidationPackagesConfigHelper.ConfigFilePath "" + Expect.equal contract.DTOType (Some DTOType.YAML) "" + Expect.equal contract.DTO (Some (DTO.Text (vpc |> ValidationPackagesConfig.toYamlString()))) "" + + testCase "toDeleteContract" <| fun _ -> + let contract = ValidationPackagesConfig.toDeleteContract vpc + Expect.equal contract.Operation Operation.DELETE "" + Expect.equal contract.Path ValidationPackagesConfigHelper.ConfigFilePath "" + Expect.equal contract.DTOType None "" + Expect.equal contract.DTO None "" + + testCase "tryFromReadContract" <| fun _ -> + let contract = { + Operation = READ + DTOType = Some DTOType.YAML + Path = ValidationPackagesConfigHelper.ConfigFilePath + DTO = Some (DTO.Text (ValidationPackagesConfig.toYamlString() vpc)) + } + let result = ValidationPackagesConfig.tryFromReadContract contract + Expect.equal result (Some vpc) "" +] + +let main = testList "ValidationPackageConfig" [ + extension_methods_tests +] \ No newline at end of file diff --git a/tests/TestingUtils/Library.fs b/tests/TestingUtils/Library.fs index 17939411..fec190fe 100644 --- a/tests/TestingUtils/Library.fs +++ b/tests/TestingUtils/Library.fs @@ -1,4 +1,4 @@ -namespace TestingUtils +namespace TestingUtils open FsSpreadsheet open ARCtrl @@ -96,6 +96,12 @@ module Expect = let inline equal actual expected message = Expect.equal actual expected message let notEqual actual expected message = Expect.notEqual actual expected message + /// Trims whitespace and normalizes lineendings to "\n" + let trimEqual (actual: string) (expected: string) message = + let a = actual.Trim().Replace("\r\n", "\n") + let e = expected.Trim().Replace("\r\n", "\n") + Expect.equal a e message + /// /// This function only verifies non-whitespace characters /// @@ -248,3 +254,4 @@ module Test = let testList = testList + let ftestList = ftestList \ No newline at end of file diff --git a/tests/TestingUtils/TestingUtils.fsproj b/tests/TestingUtils/TestingUtils.fsproj index dc0551a9..782d49df 100644 --- a/tests/TestingUtils/TestingUtils.fsproj +++ b/tests/TestingUtils/TestingUtils.fsproj @@ -28,7 +28,7 @@ - + diff --git a/tests/ValidationPackages/ARCtrl.ValidationPackages.Tests.fsproj b/tests/ValidationPackages/ARCtrl.ValidationPackages.Tests.fsproj new file mode 100644 index 00000000..b25e098c --- /dev/null +++ b/tests/ValidationPackages/ARCtrl.ValidationPackages.Tests.fsproj @@ -0,0 +1,17 @@ + + + + Exe + net8.0 + false + + + + + + + + + + + \ No newline at end of file diff --git a/tests/ValidationPackages/Main.fs b/tests/ValidationPackages/Main.fs new file mode 100644 index 00000000..a8f9c552 --- /dev/null +++ b/tests/ValidationPackages/Main.fs @@ -0,0 +1,11 @@ +module ARCtrl.FileSystem.Tests + +open Fable.Pyxpecto + +let all = testSequenced <| testList "ValidationPackages" [ + Tests.ValidationPackage.main + Tests.ValidationPackagesConfig.main +] + +[] +let main argv = Pyxpecto.runTests [||] all diff --git a/tests/ValidationPackages/ValidationPackage.Tests.fs b/tests/ValidationPackages/ValidationPackage.Tests.fs new file mode 100644 index 00000000..cc7bad9b --- /dev/null +++ b/tests/ValidationPackages/ValidationPackage.Tests.fs @@ -0,0 +1,60 @@ +module Tests.ValidationPackage + +open TestingUtils + +open ARCtrl +open ARCtrl.ValidationPackages + +let vp = ValidationPackage("name", "version") +let vp_no_version = ValidationPackage("name") + +let tests_instance_methods = testList "Instance methods" [ + testCase "Copy - name and version" <| fun _ -> + let actual = vp.Copy() + let expected = vp + Expect.equal actual expected "" + testCase "Copy - no version" <| fun _ -> + let actual = vp_no_version.Copy() + let expected = vp_no_version + Expect.equal actual expected "" + testCase "ToString - name and version" <| fun _ -> + let actual = vp.ToString() + let expected = "{\n Name = name\n Version = version\n}" + Expect.trimEqual actual expected "" + testCase "ToString - no version" <| fun _ -> + let actual = vp_no_version.ToString() + let expected = "{\n Name = name\n}" + Expect.trimEqual actual expected "" + testCase "Equals - name and version" <| fun _ -> + let actual = ValidationPackage("name", "version").Equals(vp) + let expected = true + Expect.equal actual expected "" + testCase "Equals - no version" <| fun _ -> + let actual = ValidationPackage("name").Equals(vp_no_version) + let expected = true + Expect.equal actual expected "" + testCase "GetHashCode - name and version" <| fun _ -> + let actual = ValidationPackage("name", "version").GetHashCode() + let expected = vp.GetHashCode() + Expect.equal actual expected "" + testCase "GetHashCode - no version" <| fun _ -> + let actual = ValidationPackage("name").GetHashCode() + let expected = vp_no_version.GetHashCode() + Expect.equal actual expected "" +] + +let tests_static_methods = testList "Static methods" [ + testCase "make - name and version" <| fun _ -> + let actual = ValidationPackage.make "name" (Some "version") + let expected = vp + Expect.equal actual expected "" + testCase "make - no version" <| fun _ -> + let actual = ValidationPackage.make "name" None + let expected = vp_no_version + Expect.equal actual expected "" +] + +let main = testList "ValidationPackage" [ + tests_instance_methods + tests_static_methods +] \ No newline at end of file diff --git a/tests/ValidationPackages/ValidationPackagesConfig.Tests.fs b/tests/ValidationPackages/ValidationPackagesConfig.Tests.fs new file mode 100644 index 00000000..53342825 --- /dev/null +++ b/tests/ValidationPackages/ValidationPackagesConfig.Tests.fs @@ -0,0 +1,89 @@ +module Tests.ValidationPackagesConfig + +open TestingUtils + +open ARCtrl +open ARCtrl.ValidationPackages + +let vp = ValidationPackages.ValidationPackage("name", "version") +let vp_no_version = ValidationPackages.ValidationPackage("name") + +let vpc = ValidationPackages.ValidationPackagesConfig(new ResizeArray([vp; vp_no_version ]), "arc_specification") +let vpc_no_specs = ValidationPackages.ValidationPackagesConfig(new ResizeArray([vp; vp_no_version ])) + +let tests_instance_methods = testList "Instance methods" [ + testCase "Copy - specs and packages" <| fun _ -> + let actual = vpc.Copy() + let expected = vpc + Expect.equal actual expected "" + testCase "Copy - no specs" <| fun _ -> + let actual = vpc_no_specs.Copy() + let expected = vpc_no_specs + Expect.equal actual expected "" + testCase "ToString - specs and packages" <| fun _ -> + let actual = vpc.ToString() + let expected = "{\n ARCSpecification = arc_specification\n ValidationPackages = [\n{\n Name = name\n Version = version\n};\n{\n Name = name\n}\n]\n}" + Expect.trimEqual actual expected "" + testCase "ToString - no specs" <| fun _ -> + let actual = vpc_no_specs.ToString() + let expected = "{\n ValidationPackages = [\n{\n Name = name\n Version = version\n};\n{\n Name = name\n}\n]\n}" + Expect.trimEqual actual expected "" + testCase "StructurallyEquals - specs and packages" <| fun _ -> + let actual = ValidationPackages.ValidationPackagesConfig(new ResizeArray([vp_no_version; vp]), "arc_specification").StructurallyEquals(vpc) + let expected = true + Expect.equal actual expected "" + testCase "StructurallyEquals - no specs" <| fun _ -> + let actual = ValidationPackages.ValidationPackagesConfig(new ResizeArray([vp_no_version; vp])).StructurallyEquals(vpc_no_specs) + let expected = true + Expect.equal actual expected "" + testCase "ReferenceEquals - specs and packages" <| fun _ -> + let actual = vpc.ReferenceEquals(vpc) + let expected = true + Expect.equal actual expected "" + testCase "ReferenceEquals - no specs" <| fun _ -> + let actual = vpc_no_specs.ReferenceEquals(vpc_no_specs) + let expected = true + Expect.equal actual expected "" + testCase "ReferenceEquals with other instance - specs and packages" <| fun _ -> + let actual = ValidationPackages.ValidationPackagesConfig(new ResizeArray([vp; vp_no_version ]), "arc_specification").ReferenceEquals(vpc) + let expected = false + Expect.equal actual expected "" + testCase "ReferenceEquals with other instance - no specs" <| fun _ -> + let actual = ValidationPackages.ValidationPackagesConfig(new ResizeArray([vp; vp_no_version ])).ReferenceEquals(vpc_no_specs) + let expected = false + Expect.equal actual expected "" + testCase "Equals - specs and packages" <| fun _ -> + let actual = ValidationPackages.ValidationPackagesConfig(new ResizeArray([vp_no_version; vp]), "arc_specification").Equals(vpc) + let expected = true + Expect.equal actual expected "" + testCase "Equals - no specs" <| fun _ -> + let actual = ValidationPackages.ValidationPackagesConfig(new ResizeArray([vp_no_version; vp])).Equals(vpc_no_specs) + let expected = true + Expect.equal actual expected "" + testCase "GetHashCode - specs and packages" <| fun _ -> + let actual = vpc.GetHashCode() // not sure here if different object should have same or different hash (equivalkent to StructurallyEquals) + let expected = vpc.GetHashCode() + Expect.equal actual expected "" + testCase "GetHashCode - no specs" <| fun _ -> + let actual = vpc_no_specs.GetHashCode() // not sure here if different object should have same or different hash (equivalkent to StructurallyEquals) + let expected = vpc_no_specs.GetHashCode() + Expect.equal actual expected "" + +] + +let tests_static_methods = testList "Static methods" [ + testCase "make - specs and packages" <| fun _ -> + let actual = ValidationPackagesConfig.make (new ResizeArray([vp; vp_no_version ])) (Some "arc_specification") + let expected = vpc + Expect.equal actual expected "" + testCase "make - no specs" <| fun _ -> + let actual = ValidationPackagesConfig.make (new ResizeArray([vp; vp_no_version ])) None + let expected = vpc_no_specs + Expect.equal actual expected "" +] + + +let main = testList "ValidationPackageConfig" [ + tests_instance_methods + tests_static_methods +] \ No newline at end of file diff --git a/tests/Yaml/ARCtrl.Yaml.Tests.fsproj b/tests/Yaml/ARCtrl.Yaml.Tests.fsproj new file mode 100644 index 00000000..ce2443a6 --- /dev/null +++ b/tests/Yaml/ARCtrl.Yaml.Tests.fsproj @@ -0,0 +1,17 @@ + + + + Exe + net8.0 + false + + + + + + + + + + + \ No newline at end of file diff --git a/tests/Yaml/Main.fs b/tests/Yaml/Main.fs new file mode 100644 index 00000000..1c43fc1f --- /dev/null +++ b/tests/Yaml/Main.fs @@ -0,0 +1,11 @@ +module ARCtrl.Yaml.Tests + +open Fable.Pyxpecto + +let all = testSequenced <| testList "Yaml" [ + Tests.ValidationPackage.main + Tests.ValidationPackagesConfig.main +] + +[] +let main argv = Pyxpecto.runTests [||] all diff --git a/tests/Yaml/ValidationPackage.Tests.fs b/tests/Yaml/ValidationPackage.Tests.fs new file mode 100644 index 00000000..01217989 --- /dev/null +++ b/tests/Yaml/ValidationPackage.Tests.fs @@ -0,0 +1,80 @@ +module Tests.ValidationPackage + +open TestingUtils + +open ARCtrl +open ARCtrl.ValidationPackages +open ARCtrl.Yaml + +let tests_extended = testList "extended" [ + let vp = ValidationPackages.ValidationPackage("name", "version") + let vp_no_version = ValidationPackages.ValidationPackage("name") + + let vp_yaml_string = $"""{ValidationPackage.NAME_KEY}: name +{ValidationPackage.VERSION_KEY}: version +""" + + let vp_no_version_yaml_string = $"""{ValidationPackage.NAME_KEY}: name +""" + + testList "encoder (toYamlString)" [ + testCase "name and version" <| fun _ -> + let actual = ValidationPackage.encoder vp |> Encode.toYamlString 2 + let expected = vp_yaml_string + Expect.trimEqual actual expected "" + testCase "no version" <| fun _ -> + let actual = ValidationPackage.encoder vp_no_version |> Encode.toYamlString 2 + let expected = vp_no_version_yaml_string + Expect.trimEqual actual expected "" + ] + testList "decoder (fromYamlString)" [ + testCase "name and version" <| fun _ -> + let actual = Decode.fromYamlString ValidationPackage.decoder vp_yaml_string + let expected = vp + Expect.equal actual expected "" + testCase "no version" <| fun _ -> + let actual = Decode.fromYamlString ValidationPackage.decoder vp_no_version_yaml_string + let expected = vp_no_version + Expect.equal actual expected "" + ] + testList "roundtrip (fromYamlString >> toYamlString)" [ + testCase "name and version" <| fun _ -> + let actual = + vp_yaml_string + |> Decode.fromYamlString ValidationPackage.decoder + |> ValidationPackage.encoder + |> Encode.toYamlString 2 + let expected = vp_yaml_string + Expect.trimEqual actual expected "" + testCase "no version" <| fun _ -> + let actual = + vp_no_version_yaml_string + |> Decode.fromYamlString ValidationPackage.decoder + |> ValidationPackage.encoder + |> Encode.toYamlString 2 + let expected = vp_no_version_yaml_string + Expect.trimEqual actual expected "" + ] + testList "roundtrip (toYamlString >> fromYamlString)" [ + testCase "name and version" <| fun _ -> + let actual = + vp + |> ValidationPackage.encoder + |> Encode.toYamlString 2 + |> Decode.fromYamlString ValidationPackage.decoder + let expected = vp + Expect.equal actual expected "" + testCase "no version" <| fun _ -> + let actual = + vp_no_version + |> ValidationPackage.encoder + |> Encode.toYamlString 2 + |> Decode.fromYamlString ValidationPackage.decoder + let expected = vp_no_version + Expect.equal actual expected "" + ] +] + +let main = testList "ValidationPackage" [ + tests_extended +] \ No newline at end of file diff --git a/tests/Yaml/ValidationPackageConfig.Tests.fs b/tests/Yaml/ValidationPackageConfig.Tests.fs new file mode 100644 index 00000000..ad001e7c --- /dev/null +++ b/tests/Yaml/ValidationPackageConfig.Tests.fs @@ -0,0 +1,93 @@ +module Tests.ValidationPackagesConfig + +open TestingUtils + +open ARCtrl +open ARCtrl.ValidationPackages +open ARCtrl.Yaml + +let tests_extended = testList "extended" [ + let vp = ValidationPackages.ValidationPackage("name", "version") + let vp_no_version = ValidationPackages.ValidationPackage("name") + + let vpc = ValidationPackages.ValidationPackagesConfig(new ResizeArray([vp; vp_no_version ]), "arc_specification") + let vpc_no_specs = ValidationPackages.ValidationPackagesConfig(new ResizeArray([vp; vp_no_version ])) + + let vpc_yaml_string = $"""{ValidationPackagesConfig.ARC_SPECIFICATION_KEY}: arc_specification +{ValidationPackagesConfig.VALIDATION_PACKAGES_KEY}: + - + {ValidationPackage.NAME_KEY}: name + {ValidationPackage.VERSION_KEY}: version + - + {ValidationPackage.NAME_KEY}: name +""" + + let vpc_no_specs_yaml_string = $"""validation_packages: + - + {ValidationPackage.NAME_KEY}: name + {ValidationPackage.VERSION_KEY}: version + - + {ValidationPackage.NAME_KEY}: name +""" + + testList "encoder (toYamlString)" [ + testCase "no specification validation" <| fun _ -> + let actual = ValidationPackagesConfig.encoder vpc |> Encode.toYamlString 2 + let expected = vpc_yaml_string + Expect.trimEqual actual expected "" + testCase "with specification validation" <| fun _ -> + let actual = ValidationPackagesConfig.encoder vpc_no_specs |> Encode.toYamlString 2 + let expected = vpc_no_specs_yaml_string + Expect.trimEqual actual expected "" + ] + testList "decoder (fromYamlString)" [ + testCase "name and version" <| fun _ -> + let actual = Decode.fromYamlString ValidationPackagesConfig.decoder vpc_yaml_string + let expected = vpc + Expect.equal actual expected "" + testCase "no version" <| fun _ -> + let actual = Decode.fromYamlString ValidationPackagesConfig.decoder vpc_no_specs_yaml_string + let expected = vpc_no_specs + Expect.equal actual expected "" + ] + testList "roundtrip (fromYamlString >> toYamlString)" [ + testCase "name and version" <| fun _ -> + let actual = + vpc_yaml_string + |> Decode.fromYamlString ValidationPackagesConfig.decoder + |> ValidationPackagesConfig.encoder + |> Encode.toYamlString 2 + let expected = vpc_yaml_string + Expect.trimEqual actual expected "" + testCase "no version" <| fun _ -> + let actual = + vpc_no_specs_yaml_string + |> Decode.fromYamlString ValidationPackagesConfig.decoder + |> ValidationPackagesConfig.encoder + |> Encode.toYamlString 2 + let expected = vpc_no_specs_yaml_string + Expect.trimEqual actual expected "" + ] + testList "roundtrip (toYamlString >> fromYamlString)" [ + testCase "name and version" <| fun _ -> + let actual = + vpc + |> ValidationPackagesConfig.encoder + |> Encode.toYamlString 2 + |> Decode.fromYamlString ValidationPackagesConfig.decoder + let expected = vpc + Expect.equal actual expected "" + testCase "no version" <| fun _ -> + let actual = + vpc_no_specs + |> ValidationPackagesConfig.encoder + |> Encode.toYamlString 2 + |> Decode.fromYamlString ValidationPackagesConfig.decoder + let expected = vpc_no_specs + Expect.equal actual expected "" + ] +] + +let main = testList "ValidationPackageConfig" [ + tests_extended +] \ No newline at end of file