Tests/powershell-yaml.Tests.ps1
# Copyright 2016 Cloudbase Solutions Srl # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # $here = Split-Path -Parent $MyInvocation.MyCommand.Path $moduleHome = Split-Path -Parent $here $moduleName = "powershell-yaml" $modulePath = Join-Path $moduleHome "powershell-yaml.psd1" Import-Module $modulePath InModuleScope $moduleName { # Confirm-Equality is a helper function which acts like a DeepEquals # with special attention payed to the specific types the yaml decoder # can handle. function Confirm-Equality { Param( [Parameter(Mandatory=$true)]$expected, [Parameter(Mandatory=$true)]$got ) # check for easy way out; this should work for all simple value types: if ($expected -eq $got) { return $true } # else; handle hashes and arrays specially: if ($expected -is [System.Array]) { if ($got -isnot [System.Array] -or ($expected.Count -ne $got.Count)) { return $false } # just iterate through the elements of the array comparing each one: for ($i = 0; $i -lt $expected.Count; $i = $i + 1) { if ( !(Confirm-Equality $expected.Get($i) $got.Get($i)) ) { return $false } } return $true } if ($expected -is [Hashtable]) { if ($got -isnot [Hashtable] -or ($expected.Count -ne $got.Count)) { return $false } # iterate through all the keys: $eq = $true $expected.Keys | % { if ( !$got.ContainsKey($_) ) { $eq = $false return } if ( !(Confirm-Equality $expected.Item($_) $got.Item($_)) ) { return $false } } return $true } return $false } Describe "Test encode-decode symmetry." { Context "Simple-Items" { $items = 1, "yes", 56, $null foreach ($item in $items) { It "Should represent identity to encode and decode." { $yaml = ConvertTo-Yaml $item $i = ConvertFrom-Yaml $yaml $item -eq $i | Should Be $true } } } Context "Test array handling under various circumstances." { $arr = 1, 2, "yes", @{ key = "value" }, 5, (1, "no", 3) It "Should represent identity to encode/decode arrays as arguments." { $yaml = ConvertTo-Yaml $arr $a = ConvertFrom-Yaml $yaml Confirm-Equality $arr $a | Should Be $true } It "Should represent identity to encode/decode arrays by piping them in." { $yaml = $arr | ConvertTo-Yaml $a = ConvertFrom-Yaml $yaml Confirm-Equality $arr $a | Should Be $true } It "Should be irrelevant whether we convert an array by piping it, or referencing them as an argument." { $arged = ConvertTo-Yaml $arr $piped = $arr | ConvertTo-Yaml Confirm-Equality $arged $piped | Should Be $true } } Context "Test hash handling under various circumstances." { $hash = @{ # NOTE: intentionally not considered as YAML requires dict keys # be strings. As such; decoding the encoding of this would result # in a hash with the string key of "1", as below: # 1 = 42; "1" = 42; today = @{ month = "January"; year = "2016"; timestamp = Get-Date }; arr = 1, 2, 3, "yes", @{ yes = "yes" }; yes = "no" } It "Should be symmetrical to encode and then decode the hash as an argument." { $yaml = ConvertTo-Yaml $hash $h = ConvertFrom-Yaml $yaml Confirm-Equality $hash $h | Should Be $true } It "Should be symmetrical to endocode and then decode a hash by piping it." { $yaml = $hash | ConvertTo-Yaml $h = ConvertFrom-Yaml $yaml Confirm-Equality $hash $h | Should Be $true } It "Shouldn't matter whether we reference or pipe our hashes in to the YAML functions." { $arged = ConvertTo-Yaml $hash $piped = $hash | ConvertTo-Yaml Confirm-Equality $arged $piped | Should Be $true } } } Describe "Being able to decode an externally provided string." { Context "Decoding an arbitrary YAML string correctly." { # testYaml is just a string containing some yaml to be tested below: $testYaml = @" wishlist: - [coats, hats, and, scarves] - product : A Cool Book. quantity : 1 description : I love that Cool Book. price : 55.34 total: 4443.52 note: > I can't wait. To get that Cool Book. "@ $expected = @{ wishlist = @( @("coats", "hats", "and", "scarves"), @{ product = "A Cool Book."; quantity = 1; description = "I love that Cool Book."; price = 55.34 } ); total = 4443.52; comment = "I can't wait. To get that Cool Book." } $res = ConvertFrom-Yaml $testYaml It "Should decode the YAML string as expected." { Confirm-Equality $expected $res | Should Be $true } } } Describe "Test ConvertTo-Yaml -OutFile parameter behavior" { Context "Providing -OutFile with invalid prefix." { $testPath = "/some/bogus/path" $testObject = 42 # mock Test-Path to fail so the test for the directory of the -OutFile fails: Mock Test-Path { return $false } -Verifiable -ParameterFilter { $OutFile -eq $testPath } It "Should refuse to work with an -OutFile with an invalid prefix." { { ConvertTo-Yaml $testObject -OutFile $testPath } | Should Throw "Parent folder for specified path does not exist" } It "Should verify that all the required mocks were called." { Assert-VerifiableMocks } } Context "Providing existing -OutFile without -Force." { $testPath = "/some/bogus/path" $testObject = "A random string this time." # mock Test-Path to succeed so the -OutFile seems to exist: Mock Test-Path { return $true } -Verifiable -ParameterFilter { $OutFile -eq $testPath } It "Should refuse to work for an existing -OutFile but no -Force flag." { { ConvertTo-Yaml $testObject -OutFile $testPath } | Should Throw "Target file already exists. Use -Force to overwrite." } It "Should verify that all the required mocks were called." { Assert-VerifiableMocks } } Context "Providing a valid -OutFile." { $testObject = @{ yes = "No"; "arr" = @(1, 2, 3) } $testPath = [System.IO.Path]::GetTempFileName() Remove-Item -Force $testPath # must be deleted for the test It "Should succesfully write the expected content to the specified -OutFile." { $yaml = ConvertTo-Yaml $testObject ConvertTo-Yaml $testObject -OutFile $testPath Compare-Object $yaml (Get-Content $testPath) | Should Be $true } # NOTE: the below assertion relies on the above writing its file. It "Should succesfully write the expected content to the specified -OutFile with -Force even if it exists." { $newTestObject = @(1, "two", @("arr", "ay"), @{ yes = "no"; answer = 42 }) $yaml = ConvertTo-Yaml $newTestObject ConvertTo-Yaml $newTestObject -OutFile $testPath -Force Compare-Object $yaml (Get-Content $testPath) | Should Be $true } } } } |