Tests/Private/Config.Tests.ps1
|
BeforeDiscovery { Import-Module (Join-Path $PSScriptRoot '..\..\Use-Onyphe.psd1') -DisableNameChecking -Force } Describe 'Private/Config functions' -Tag 'Unit' { InModuleScope 'Use-Onyphe' { Context 'Get-OnypheConfigPath' { It 'returns Use-Onyphe\Use-Onyphe-Config.json under the user profile' { (Get-OnypheConfigPath) | Should -Be (Join-Path $home 'Use-Onyphe\Use-Onyphe-Config.json') } } Context 'Save-OnypheConfigFile / Read-OnypheConfigFile round-trip' { BeforeEach { $script:ConfigTestPath = Join-Path $TestDrive 'Use-Onyphe-Config.json' if (Test-Path $script:ConfigTestPath) { Remove-Item -Path $script:ConfigTestPath -Force } Mock Get-OnypheConfigPath { $script:ConfigTestPath } } It 'writes the config object as JSON, creating the containing directory' { $DeepPath = Join-Path $TestDrive 'nested\dir\Use-Onyphe-Config.json' Mock Get-OnypheConfigPath { $DeepPath } $Config = [PSCustomObject]@{ version = '1.0'; APIKey = [PSCustomObject]@{ Salt = 'abc'; EncryptedAPIKey = 'xyz' } } Save-OnypheConfigFile -Config $Config Test-Path $DeepPath | Should -BeTrue (Get-Content $DeepPath -Raw | ConvertFrom-Json).APIKey.Salt | Should -Be 'abc' } It 'reads back a previously saved config unchanged' { $Config = [PSCustomObject]@{ version = '1.0' APIKey = [PSCustomObject]@{ Salt = 'abc'; EncryptedAPIKey = 'xyz' } DataModel = [PSCustomObject]@{ apis = @('a','b'); filters = @('f'); functions = @('fn') } } Save-OnypheConfigFile -Config $Config $Read = Read-OnypheConfigFile $Read.APIKey.Salt | Should -Be 'abc' @($Read.DataModel.apis) | Should -Be @('a','b') } It 'returns a default empty config when no JSON file and no legacy XML exists' { Mock ConvertFrom-OnypheLegacyConfig { $null } $Config = Read-OnypheConfigFile $Config.version | Should -Be '1.0' $Config.APIKey.EncryptedAPIKey | Should -BeNullOrEmpty $Config.DataModel.apis | Should -BeNullOrEmpty } It 'does not leave a temporary file behind after a successful write' { $DeepDir = Join-Path $TestDrive 'atomic-write-dir' $DeepPath = Join-Path $DeepDir 'Use-Onyphe-Config.json' Mock Get-OnypheConfigPath { $DeepPath } $Config = [PSCustomObject]@{ version = '1.0'; APIKey = [PSCustomObject]@{ Salt = 'abc'; EncryptedAPIKey = 'xyz' } } Save-OnypheConfigFile -Config $Config (Get-ChildItem -Path $DeepDir -Force).Name | Should -Be 'Use-Onyphe-Config.json' } It 'throws a descriptive error when the JSON file is corrupted' { Set-Content -Path $script:ConfigTestPath -Value '{ not valid json' -Encoding UTF8 { Read-OnypheConfigFile } | Should -Throw '*corrupted or not valid JSON*' } It 'migrates and persists a legacy config when the JSON file is missing but legacy data is found' { $Legacy = [PSCustomObject]@{ version = '1.0' APIKey = [PSCustomObject]@{ Salt = 'legacy-salt'; EncryptedAPIKey = 'legacy-key' } Proxy = [PSCustomObject]@{} DataModel = [PSCustomObject]@{ apis = $null; filters = $null; functions = $null } Logging = [PSCustomObject]@{} } Mock ConvertFrom-OnypheLegacyConfig { $Legacy } $Config = Read-OnypheConfigFile $Config.APIKey.Salt | Should -Be 'legacy-salt' Test-Path $script:ConfigTestPath | Should -BeTrue } } Context 'ConvertFrom-OnypheLegacyConfig' { It 'returns $null when neither legacy file exists' { Mock Test-Path { $false } ConvertFrom-OnypheLegacyConfig | Should -BeNullOrEmpty } It 'migrates the legacy API key file, base64-encoding the salt' { Mock Test-Path { $Path -like '*Use-Onyphe-Config.xml' } Mock Import-Clixml { if ($Path -like '*Use-Onyphe-Config.xml') { @{ Salt = [byte[]](1,2,3,4); EncryptedAPIKey = 'legacy-encrypted' } } } $Result = ConvertFrom-OnypheLegacyConfig $Result.APIKey.EncryptedAPIKey | Should -Be 'legacy-encrypted' $Result.APIKey.Salt | Should -Be ([Convert]::ToBase64String([byte[]](1,2,3,4))) } It 'migrates the legacy data-model file' { Mock Test-Path { $Path -like '*Onyphe-Data-Model.xml' } Mock Import-Clixml { if ($Path -like '*Onyphe-Data-Model.xml') { [PSCustomObject]@{ apis = @('a'); filters = @('f'); functions = @('fn') } } } $Result = ConvertFrom-OnypheLegacyConfig @($Result.DataModel.apis) | Should -Be @('a') } } Context 'Get-OnypheLoggingConfig' { It 'defaults to Enabled=$false, MinimumLevel=Information, Mode=File when Logging is absent' { $Config = [PSCustomObject]@{ version = '1.0' } $Logging = Get-OnypheLoggingConfig -Config $Config $Logging.Enabled | Should -BeFalse $Logging.MinimumLevel | Should -Be 'Information' $Logging.Mode | Should -Be 'File' } It 'honors an explicit Logging section' { $Config = [PSCustomObject]@{ Logging = [PSCustomObject]@{ Enabled = $true MinimumLevel = 'Debug' Mode = 'EventLog' } } $Logging = Get-OnypheLoggingConfig -Config $Config $Logging.Enabled | Should -BeTrue $Logging.MinimumLevel | Should -Be 'Debug' $Logging.Mode | Should -Be 'EventLog' } It 'falls back to Information for an unrecognized MinimumLevel and warns once' { $Config = [PSCustomObject]@{ Logging = [PSCustomObject]@{ MinimumLevel = 'Bogus' } } $script:LoggingConfigWarned = $false $Logging = Get-OnypheLoggingConfig -Config $Config -WarningVariable Warnings -WarningAction SilentlyContinue $Logging.MinimumLevel | Should -Be 'Information' @($Warnings).Count | Should -Be 1 } } } } |