tests/functions/Resolve-SMAXEntityInput.Tests.ps1

BeforeAll {
    $modulePath = Join-Path $PSScriptRoot '..\..\SMAX.psd1'
    Import-Module $modulePath -Force

    $script:entityDescription = @{
        CurrentAssignment = [pscustomobject]@{
            name           = 'CurrentAssignment'
            logical_type   = 'ENUM'
            remoteType     = $null
            possibleValues = [pscustomobject]@{
                Incident    = 'Incident'
                ServiceDesk = 'Service Desk'
            }
        }
        AssignedToGroup = [pscustomobject]@{
            name           = 'AssignedToGroup'
            logical_type   = 'ENTITY_LINK'
            remoteType     = 'PersonGroup'
            possibleValues = $null
        }
        DisplayLabel = [pscustomobject]@{
            name           = 'DisplayLabel'
            logical_type   = 'STRING'
            remoteType     = $null
            possibleValues = $null
        }
        UserOptions = [pscustomobject]@{
            name           = 'UserOptions'
            logical_type   = 'STRING'
            remoteType     = $null
            possibleValues = $null
        }
    }
}

Describe 'Resolve-SMAXEntityInput' {
    BeforeEach {
        Mock Get-SMAXEntityDescription {
            $script:entityDescription
        } -ModuleName SMAX

        Mock Get-SMAXEntity {
            [pscustomobject]@{ Id = '1001' }
        } -ModuleName SMAX
    }

    It 'accepts a JSON string and canonicalizes property names' {
        $result = Resolve-SMAXEntityInput -InputObject '{"displaylabel":"Test"}' -EntityType Request -Connection 'test'

        $result.DisplayLabel | Should -Be 'Test'
        $result.Keys | Should -Be @('DisplayLabel')
    }

    It 'accepts a PSCustomObject and normalizes ENUM values' {
        $input = [pscustomobject]@{ CurrentAssignment = 'servicedesk' }

        $result = Resolve-SMAXEntityInput -InputObject $input -EntityType Request -Connection 'test'

        $result.CurrentAssignment | Should -Be 'ServiceDesk'
    }

    It 'accepts a hashtable through the pipeline' {
        $result = @{ DisplayLabel = 'Pipeline input' } |
            Resolve-SMAXEntityInput -EntityType Request -Connection 'test'

        $result.DisplayLabel | Should -Be 'Pipeline input'
    }

    It 'resolves root ENTITY_LINK lookups to an Id' {
        $result = Resolve-SMAXEntityInput -InputObject @{ 'lookup.AssignedToGroup' = "Name='Operations'" } -EntityType Request -Connection 'test'

        $result.AssignedToGroup | Should -Be '1001'
        Should -Invoke Get-SMAXEntity -ModuleName SMAX -Times 1 -ParameterFilter {
            $EntityType -eq 'PersonGroup' -and $Filter -eq "Name='Operations'"
        }
    }

    It 'resolves complete UserOptions lookup tokens and leaves partial tokens unchanged' {
        $input = @{
            UserOptions = '{"complexTypeProperties":[{"properties":{"Location":"{{lookup:Location|DisplayLabel=''Extended Zone''}}","Note":"prefix {{lookup:Location|DisplayLabel=''Extended Zone''}}"}}]}'
        }

        $result = Resolve-SMAXEntityInput -InputObject $input -EntityType Request -Connection 'test'
        $userOptions = $result.UserOptions | ConvertFrom-Json

        $userOptions.complexTypeProperties[0].properties.Location | Should -Be '1001'
        $userOptions.complexTypeProperties[0].properties.Note | Should -Be "prefix {{lookup:Location|DisplayLabel='Extended Zone'}}"
    }

    It 'rejects duplicate canonical properties' {
        {
            Resolve-SMAXEntityInput -InputObject @{ DisplayLabel = 'One'; 'lookup.DisplayLabel' = "Name='Two'" } -EntityType Request -Connection 'test'
        } | Should -Throw "*specified more than once*"
    }

    It 'rejects a lookup with no matching entity' {
        Mock Get-SMAXEntity { @() } -ModuleName SMAX

        {
            Resolve-SMAXEntityInput -InputObject @{ 'lookup.AssignedToGroup' = "Name='Unknown'" } -EntityType Request -Connection 'test'
        } | Should -Throw "*did not find*"
    }

    It 'rejects a lookup with multiple matching entities' {
        Mock Get-SMAXEntity {
            @([pscustomobject]@{ Id = '1001' }, [pscustomobject]@{ Id = '1002' })
        } -ModuleName SMAX

        {
            Resolve-SMAXEntityInput -InputObject @{ 'lookup.AssignedToGroup' = "Name='Duplicate'" } -EntityType Request -Connection 'test'
        } | Should -Throw "*found multiple*"
    }

    It 'rejects malformed JSON input' {
        {
            Resolve-SMAXEntityInput -InputObject '{invalid}' -EntityType Request -Connection 'test'
        } | Should -Throw '*valid JSON*'
    }
}