From 4a41d56955ae0402239df25c342fc6ff5722994e Mon Sep 17 00:00:00 2001 From: Tw93 Date: Mon, 23 Mar 2026 20:07:22 +0800 Subject: [PATCH] fix(windows): initialize visual defaults safely --- lib/core/base.ps1 | 32 ++++++++++++++++++++++---------- tests/Commands.Tests.ps1 | 9 ++++++--- tests/Core.Tests.ps1 | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/lib/core/base.ps1 b/lib/core/base.ps1 index a0a2dc9..ab0d73b 100644 --- a/lib/core/base.ps1 +++ b/lib/core/base.ps1 @@ -47,24 +47,36 @@ $script:DefaultIcons = @{ Trash = [char]0x2718 # ✘ (trash substitute) } -function Initialize-MoleVisualDefaults { - if (-not ($script:Colors -is [hashtable])) { - $script:Colors = @{} +function Get-OrCreateScriptHashtable { + param( + [Parameter(Mandatory)] + [string]$Name + ) + + $existing = Get-Variable -Name $Name -Scope Script -ErrorAction SilentlyContinue + if ($existing -and $existing.Value -is [hashtable]) { + return $existing.Value } + $table = @{} + Set-Variable -Name $Name -Scope Script -Value $table + return $table +} + +function Initialize-MoleVisualDefaults { + $colors = Get-OrCreateScriptHashtable -Name "Colors" + foreach ($entry in $script:DefaultColors.GetEnumerator()) { - if (-not $script:Colors.ContainsKey($entry.Key)) { - $script:Colors[$entry.Key] = $entry.Value + if (-not $colors.ContainsKey($entry.Key)) { + $colors[$entry.Key] = $entry.Value } } - if (-not ($script:Icons -is [hashtable])) { - $script:Icons = @{} - } + $icons = Get-OrCreateScriptHashtable -Name "Icons" foreach ($entry in $script:DefaultIcons.GetEnumerator()) { - if (-not $script:Icons.ContainsKey($entry.Key)) { - $script:Icons[$entry.Key] = $entry.Value + if (-not $icons.ContainsKey($entry.Key)) { + $icons[$entry.Key] = $entry.Value } } } diff --git a/tests/Commands.Tests.ps1 b/tests/Commands.Tests.ps1 index ac1be19..59d391d 100644 --- a/tests/Commands.Tests.ps1 +++ b/tests/Commands.Tests.ps1 @@ -6,6 +6,7 @@ BeforeAll { $script:WindowsDir = Split-Path -Parent $PSScriptRoot $script:BinDir = Join-Path $script:WindowsDir "bin" $script:InstallScript = Join-Path $script:WindowsDir "install.ps1" + $script:VisualDefaultsErrorPattern = 'property ''Solid'' cannot be found|找不到属性.?Solid|VariableIsUndefined|\$script:Colors' } Describe "Clean Command" { @@ -49,7 +50,7 @@ Describe "Clean Command" { Stop-Job $job -ErrorAction SilentlyContinue Remove-Job $job -Force -ErrorAction SilentlyContinue - $output | Should -Not -Match "property 'Solid' cannot be found|找不到属性.?Solid" + $output | Should -Not -Match $script:VisualDefaultsErrorPattern } } } @@ -175,7 +176,9 @@ Describe "Main Entry Point" { It "Should show version without error" { $result = & powershell -ExecutionPolicy Bypass -File $script:MolePath -Version 2>&1 $result | Should -Not -BeNullOrEmpty - $result -join "`n" | Should -Match "Mole|v\d+\.\d+" + $output = $result -join "`n" + $output | Should -Not -Match $script:VisualDefaultsErrorPattern + $output | Should -Match "Mole|v\d+\.\d+" } It "Should not throw missing Solid property errors during menu startup" { @@ -189,7 +192,7 @@ Describe "Main Entry Point" { Stop-Job $job -ErrorAction SilentlyContinue Remove-Job $job -Force -ErrorAction SilentlyContinue - $output | Should -Not -Match "property 'Solid' cannot be found|找不到属性.?Solid" + $output | Should -Not -Match $script:VisualDefaultsErrorPattern } It "Should list available commands in help" { diff --git a/tests/Core.Tests.ps1 b/tests/Core.Tests.ps1 index 1423b69..e9080f4 100644 --- a/tests/Core.Tests.ps1 +++ b/tests/Core.Tests.ps1 @@ -37,6 +37,41 @@ Describe "Base Module" { } } + Context "Visual Defaults Initialization" { + BeforeEach { + $script:OriginalColors = $script:Colors.Clone() + $script:OriginalIcons = $script:Icons.Clone() + } + + AfterEach { + $script:Colors = $script:OriginalColors.Clone() + $script:Icons = $script:OriginalIcons.Clone() + } + + It "Should initialize missing visual tables under strict mode" { + Remove-Variable -Name Colors -Scope Script -ErrorAction SilentlyContinue + Remove-Variable -Name Icons -Scope Script -ErrorAction SilentlyContinue + + { Initialize-MoleVisualDefaults } | Should -Not -Throw + $script:Colors.Cyan | Should -Not -BeNullOrEmpty + $script:Colors.Green | Should -Not -BeNullOrEmpty + $script:Icons.Solid | Should -Not -BeNullOrEmpty + $script:Icons.Trash | Should -Not -BeNullOrEmpty + } + + It "Should preserve existing values while filling missing defaults" { + $script:Colors = @{ Cyan = "custom-cyan" } + $script:Icons = @{ Solid = "*" } + + Initialize-MoleVisualDefaults + + $script:Colors.Cyan | Should -Be "custom-cyan" + $script:Colors.Green | Should -Not -BeNullOrEmpty + $script:Icons.Solid | Should -Be "*" + $script:Icons.Admin | Should -Not -BeNullOrEmpty + } + } + Context "Test-IsAdmin" { It "Should return a boolean" { $result = Test-IsAdmin