TypeFormat.tests.ps1



Describe 'Format-TypeTable' {
    BeforeAll {
        Import-Module $PSScriptRoot/TypeFormat.psm1 -Force
    }

    Context 'Metadata' {
        It 'Adds Type Metadata' {
            $actual = Get-ChildItem -File $PSScriptRoot/TypeFormat.psm1
            | Format-TypeTable -NoPersist

            $actual[0].TypeNames | Should -Contain 'System.IO.FileInfo'
        }
        It 'Adds Property Metadata (<Name>)' {
            $actual = Get-ChildItem -File $PSScriptRoot/TypeFormat.psm1
            | Format-TypeTable -NoPersist -Property $Property, Length

            $actual[0].CalculatedProperties.Count | Should -HaveCount 1
            $actual[0].CalculatedProperties['NamePlusBang'] | Should -BeOfType [ScriptBlock]
            $actual[0].CalculatedProperties['NamePlusBang'].Ast.ToString() | Should -Be { $_.Name + '!' }.Ast.ToString()
        } -TestCases @{
            Name     = 'N/E'
            Property = @{
                N = 'NamePlusBang'
                E = { $_.Name + '!' }
            }
        },
        @{
            Name     = 'Name/E'
            Property = @{
                Name = 'NamePlusBang'
                E    = { $_.Name + '!' }
            }
        },
        @{
            Name     = 'N/Expression'
            Property = @{
                N          = 'NamePlusBang'
                Expression = { $_.Name + '!' }
            }
        },
        @{
            Name     = 'Name/Expression'
            Property = @{
                Name       = 'NamePlusBang'
                Expression = { $_.Name + '!' }
            }
        }
    }

    Context 'New Type' {
        BeforeAll {
            class ___TypeFormatTestType {
                [string] $ShownProperty
                [string] $HiddenProperty
                [string] $CustomViewProperty
            }
            $SCRIPT:testType = [___TypeFormatTestType]@{
                ShownProperty  = 'Shown'
                HiddenProperty = 'Hidden'
            }
        }

        AfterEach {
            RemoveFormatType '___TypeFormatTestType'
        }

        It 'Specific Properties' {
            $testType
            | Format-TypeTable ShownProperty

            # Check that the default formatting looks as expected.
            ($testType | Format-Table)[0].shapeInfo.tableColumnInfoList.label | Should -Be 'ShownProperty'
        }

        It 'Custom View Name' {

            $testType
            | Format-TypeTable ShownProperty, CustomViewProperty -ViewName PesterCustom

            #Check that the custom format was loaded
            ([Runspace]::DefaultRunspace.InitialSessionState.Formats | Where-Object FormatData -Match 'TypeFormatTestType').FormatData.FormatViewDefinition.Name

            # Check that the default formatting looks as expected when used with -View
            ($testType | Format-Table -View PesterCustom)[0].shapeInfo.tableColumnInfoList.label | Should -Be 'ShownProperty', 'CustomViewProperty'
            ($testType | Format-TypeTable -View PesterCustom)[0].shapeInfo.tableColumnInfoList.label | Should -Be 'ShownProperty', 'CustomViewProperty'
        }

        It 'Calculated Property' {
            $testType
            | Format-TypeTable ShownProperty, @{ N = 'HiddenPlusBang'; E = { $_.HiddenProperty + '!' } }

            # Check that the default formatting looks as expected.
            ($testType | Format-Table)[0].shapeInfo.tableColumnInfoList.label | Should -Be 'ShownProperty', 'HiddenPlusBang'
        }
        It 'Multiple Calculated Properties' {
            $testType
            | Format-TypeTable ShownProperty, @{ N = 'HiddenPlusBang'; E = { $_.HiddenProperty + '!' } }, @{ N = 'HiddenPlusBangBang'; E = { $_.HiddenProperty + '!!' } }

            # Check that the default formatting looks as expected.
            ($testType | Format-Table)[0].shapeInfo.tableColumnInfoList.label | Should -Be 'ShownProperty', 'HiddenPlusBang', 'HiddenPlusBangBang'
        }

        It 'HideTableHeaders' {
            $testType
            | Format-TypeTable ShownProperty -HideTableHeaders -ViewName 'PesterTableHeaderTest'

            # Check that the default formatting looks as expected.
            $RunspaceFormats[-1].FormatData.FormatViewDefinition[0].Name | Should -Be 'PesterTableHeaderTest'
            $RunspaceFormats[-1].FormatData.FormatViewDefinition[0].Control.HideTableHeaders | Should -BeTrue
        }

        It 'AutoSize' {
            $testType
            | Format-TypeTable -AutoSize ShownProperty -ViewName 'PesterTableAutosizeTest'

            # Check that the default formatting looks as expected.
            $RunspaceFormats[-1].FormatData.FormatViewDefinition[0].Name | Should -Be 'PesterTableAutosizeTest'
            $RunspaceFormats[-1].FormatData.FormatViewDefinition[0].Control.AutoSize | Should -BeTrue
        }
        It 'Wrap' {
            $testType
            | Format-TypeTable -Wrap ShownProperty -ViewName 'PesterTableWrapTest'

            # Check that the default formatting looks as expected.
            $RunspaceFormats[-1].FormatData.FormatViewDefinition[0].Name | Should -Be 'PesterTableWrapTest'
            $RunspaceFormats[-1].FormatData.FormatViewDefinition[0].Control.Rows.Wrap | Should -BeTrue
        }

        It 'GroupBy' {
            $testType
            | Format-TypeTable -GroupBy ShownProperty -ViewName 'PesterGroupByTest'

            # Check that the default formatting looks as expected.
            $RunspaceFormats[-1].FormatData.FormatViewDefinition[0].Name | Should -Be 'PesterGroupByTest'
            $RunspaceFormats[-1].FormatData.FormatViewDefinition[0].Control.GroupBy.Expression.Value
            | Should -Be 'ShownProperty'
        }

        It 'NoPersist' {
            $testType
            | Format-TypeTable ShownProperty -NoPersist -ViewName 'PesterNoPersistTest'

            # Check that the default formatting looks as expected.
            $RunspaceFormats[-1].FormatData | Should -BeNullOrEmpty
        }

        It 'Errors on Raw PSCustomObject' {
            {
                [pscustomobject]@{ ShownProperty = 'Shown' }
                | Format-TypeTable ShownProperty
            }
            | Should -Throw -ExceptionType ([NotSupportedException])
        }

        It 'Errors on Multiple PSCustomObject Type Names' {
            {
                [pscustomobject]@{ ShownProperty = 'Shown'; PSTypeName = 'One' }
                | ForEach-Object { $_.PSTypeNames.Insert(0, 'Two'); $_ }
                | Format-TypeTable ShownProperty
            }
            | Should -Throw -ExceptionType ([NotImplementedException])
        }
    }

    Context 'Existing Type' {
        AfterEach {
            #Cleanup
            if ('System.IO.FileInfo' -eq $RunspaceFormats[0].FormatData) {
                $RunspaceFormats.RemoveItem(0)
                Update-FormatData
            }
        }
        It 'Prepends on Existing Type' {
            (Get-Item $PSScriptRoot/TypeFormat.tests.ps1)
            | Format-TypeTable Name, Length

            $RunspaceFormats[0].FormatData.TypeName | Should -Be 'System.IO.FileInfo'
            $RunspaceFormats[0].FormatData.FormatViewDefinition[0].Name | Should -Be 'CustomTypeTableView'
        }
    }
}


#Utility Functions
BeforeAll {
    $SCRIPT:RunspaceFormats = [Runspace]::DefaultRunspace.InitialSessionState.Formats
    function RemoveFormatType ($Type) {
        #Cleanup the format data
        $formats = [Runspace]::DefaultRunspace.InitialSessionState.Formats

        $i = -1
        $formats
        | Where-Object {
            $i++
            $_.FormatData -Match $Type
        }
        | Select-Object -First 1
        | Out-Null

        $formats.RemoveItem($i)
        Update-FormatData
    }
}