Csv.Tests.ps1

####################################################################################################
# Declarations
####################################################################################################

# Set InformationPreference
$InformationPreference = "Continue"

####################################################################################################
# Functions
####################################################################################################

# Import other BitTitan.Runbooks modules
Import-BT_Module BitTitan.Runbooks.Common

####################################################################################################
# The tests
####################################################################################################

describe "Modules/BitTitan.Modules.Common/Csv/ConvertTo-CsvObject" -Tags "module", "common", "unit" {

    # Prepare the input
    $csvString = @"
sep=,
"name1","name2","name3"
"1 ",2,"-1"
True,"False","TRUE "
"@


    it "converts a CSV string to a CSV object with no additional processing" {
        # Call the function
        $csvObject = ConvertTo-CsvObject $csvString -ConvertBooleans:$false

        # Verify the output
        $csvObject.GetType().Name | Should Be "Object[]"
        $csvObject.length | Should Be 2
        $csvObject[0].name1 | Should Be "1 "
        $csvObject[0].name2 | Should Be 2
        $csvObject[0].name3 | Should Be "-1"
        $csvObject[1].name1 | Should Be "True"
        $csvObject[1].name2 | Should Be "False"
        $csvObject[1].name3 | Should Be "TRUE "
    }

    it "converts a CSV string to a CSV object converting the booleans" {
        # Call the function
        $csvObject = ConvertTo-CsvObject $csvString

        # Verify the output
        $csvObject.GetType().Name | Should Be "Object[]"
        $csvObject.length | Should Be 2
        $csvObject[0].name1 | Should Be "1 "
        $csvObject[0].name2 | Should Be 2
        $csvObject[0].name3 | Should Be "-1"
        $csvObject[1].name1 | Should Be $true
        $csvObject[1].name2 | Should Be $false
        $csvObject[1].name3 | Should Be $true
    }

    it "converts a CSV string to a CSV object converting the booleans and trimming the strings" {
        # Call the function
        $csvObject = ConvertTo-CsvObject $csvString -TrimStrings

        # Verify the output
        $csvObject.GetType().Name | Should Be "Object[]"
        $csvObject.length | Should Be 2
        $csvObject[0].name1 | Should Be "1"
        $csvObject[0].name2 | Should Be 2
        $csvObject[0].name3 | Should Be "-1"
        $csvObject[1].name1 | Should Be $true
        $csvObject[1].name2 | Should Be $false
        $csvObject[1].name3 | Should Be $true
    }

    it "converts a CSV string to a CSV object converting the booleans and trimming the strings and converting the numbers" {
        # Call the function
        $csvObject = ConvertTo-CsvObject $csvString -TrimStrings -ConvertIntegersMaxLength 2

        # Verify the output
        $csvObject.GetType().Name | Should Be "Object[]"
        $csvObject.length | Should Be 2
        $csvObject[0].name1 | Should Be 1
        $csvObject[0].name2 | Should Be 2
        $csvObject[0].name3 | Should Be -1
        $csvObject[1].name1 | Should Be $true
        $csvObject[1].name2 | Should Be $false
        $csvObject[1].name3 | Should Be $true
    }
}

describe "Modules/BitTitan.Modules.Common/Csv/ConvertTo-CsvString" -Tags "module", "common", "unit" {

    # Prepare the input
    $csvObject = @(
        [PSCustomObject]@{
            Name1 = "1"
            Name2 = $true
            Name3 = $false
        },
        [PSCustomObject]@{
            Name1 = 2
            Name2 = $false
            Name3 = $true
        }
    )

    context "when there are no complications" {

        it "converts a CSV object to a CSV string" {
            # Call the function
            $csvString = ConvertTo-CsvString $csvObject

            # Verify the output
            $expectedOutput = @"
sep=,
"name1","name2","name3"
"1","True","False"
"2","False","True"
 
"@

            $csvString | Should Be $expectedOutput
        }
    }
}

describe "Modules/BitTitan.Runbooks.Common/Csv/Get-FilteredCsvString" -Tags "module", "common", "unit" {

    context "when given a CSV and no specified columns" {
        # Set up the function parameters
        $csv = @"
sep=,
"name1","name2","name3"
"1","True","False"
"2","False","True"
 
"@

        $columns = ""

        it "returns the same CSV" {
            # Call the function
            $filteredCsv = Get-FilteredCsvString -Csv $csv -Columns $columns -Filtering "and"

            # Verify the output
            $filteredCsv | Should Be $csv
        }
    }

    context "when given a CSV and one specified column" {
        # Set up the function parameters
        $csv = @"
sep=,
"name1","name2","name3"
"1","True","False"
"2","False","True"
 
"@

        $columns = "name2"

        it "filters the CSV by the column using 'and' filtering" {
            # Call the function
            $filteredCsv = Get-FilteredCsvString -Csv $csv -Columns $columns -Filtering "and"

            # Verify the output
            $expectedCsv = @"
sep=,
"name1","name2","name3"
"1","True","False"
 
"@

            $filteredCsv | Should Be $expectedCsv
        }

        it "filters the CSV by the column using 'or' filtering" {
            # Call the function
            $filteredCsv = Get-FilteredCsvString -Csv $csv -Columns $columns -Filtering "or"

            # Verify the output
            $expectedCsv = @"
sep=,
"name1","name2","name3"
"1","True","False"
 
"@

            $filteredCsv | Should Be $expectedCsv
        }
    }

    context "when given a CSV and more than one specified column" {
        # Set up the function parameters
        $csv = @"
sep=,
"name1","name2","name3"
"1","True","False"
"2","False","True"
 
"@

        $columns = "name2, name3"

        it "filters the CSV by columns using 'and' filtering" {
            # Call the function
            $filteredCsv = Get-FilteredCsvString -Csv $csv -Columns $columns -Filtering "and"

            # Verify the output
            $filteredCsv | Should Be $null
        }

        it "filters the CSV by the column using 'or' filtering" {
            # Call the function
            $filteredCsv = Get-FilteredCsvString -Csv $csv -Columns $columns -Filtering "or"

            # Verify the output
            $expectedCsv = @"
sep=,
"name1","name2","name3"
"1","True","False"
"2","False","True"
 
"@

            $filteredCsv | Should Be $expectedCsv
        }
    }

    context "when given a CSV and a column which does not exist" {
        # Set up the function parameters
        $csv = @"
sep=,
"name1","name2","name3"
"1","True","False"
"2","False","True"
 
"@

        $columns = "name4"

        it "filters the CSV by columns using 'and' filtering" {
            # Call the function
            $filteredCsv = Get-FilteredCsvString -Csv $csv -Columns $columns -Filtering "and"

            # Verify the output
            $filteredCsv | Should Be $null
        }

        it "filters the CSV by the column using 'or' filtering" {
            # Call the function
            $filteredCsv = Get-FilteredCsvString -Csv $csv -Columns $columns -Filtering "or"

            # Verify the output
            $filteredCsv | Should Be $null
        }
    }
}

describe "Modules/BitTitan.Runbooks.Common/Csv/Get-CombinedCsvString" -Tags "module", "common", "unit" {

    context "when all the CSVs contain the same columns" {
        # Set up the function parameters
        $csvStrings = @(
            @"
sep=,
"name1","name2","name3","name4"
"0","False","False","False"
"1","False","False","True"
"2","False","True","False"
 
"@
,
            @"
sep=,
"name1","name2","name3","name4"
"3","False","True","True"
"4","True","False","False"
"5","True","False","True"
 
"@
,
            @"
sep=,
"name1","name2","name3","name4"
"6","True","True","False"
"7","True","True","True"
 
"@

        )

        it "combines the CSVs" {
            # Call the function
            $combinedCsv = Get-CombinedCsvString -CsvStrings $csvStrings

            # Verify the output
            $expectedCsv = @"
sep=,
"name1","name2","name3","name4"
"0","False","False","False"
"1","False","False","True"
"2","False","True","False"
"3","False","True","True"
"4","True","False","False"
"5","True","False","True"
"6","True","True","False"
"7","True","True","True"
 
"@

            $combinedCsv | Should Be $expectedCsv
        }
    }

    context "when the CSVs contain different columns" {
        # Set up the function parameters
        $csvStrings = @(
            @"
sep=,
"name1","name2","name3","name4"
"0","False","False","False"
"1","False","False","True"
"2","False","True","False"
 
"@
,
            @"
sep=,
"name5","name6","name7","name8"
"3","False","True","True"
"4","True","False","False"
"5","True","False","True"
 
"@
,
            @"
sep=,
"name9","name10","name11","name12"
"6","True","True","False"
"7","True","True","True"
 
"@

        )

        it "combines the CSVs" {
            # Call the function
            $combinedCsv = Get-CombinedCsvString -CsvStrings $csvStrings

            # Verify the output
            $expectedCsv = @"
sep=,
"name1","name2","name3","name4","name10","name11","name12","name5","name6","name7","name8","name9"
"0","False","False","False",,,,,,,,
"1","False","False","True",,,,,,,,
"2","False","True","False",,,,,,,,
,,,,,,,"3","False","True","True",
,,,,,,,"4","True","False","False",
,,,,,,,"5","True","False","True",
,,,,"True","True","False",,,,,"6"
,,,,"True","True","True",,,,,"7"
 
"@

            $combinedCsv | Should Be $expectedCsv
        }
    }

    context "when there are any invalid CSVs" {
        # Set up the function parameters
        $csvStrings = @(
            @"
sep=,
"name1","name2","name3","name4"
"0","False","False","False"
"1","False","False","True"
"2","False","True","False"
 
"@
,
            " ",
            @"
sep=,
"name9","name10","name11","name12"
"6","True","True","False"
"7","True","True","True"
 
"@

        )

        it "returns null" {
            # Call the function
            $combinedCsv = Get-CombinedCsvString -CsvStrings $csvStrings -ErrorAction SilentlyContinue

            # Verify the output
            $combinedCsv | Should Be $null
        }
    }
}