diff --git a/.github/tests/Unit/WinCleaner.Tests.ps1 b/.github/tests/Unit/WinCleaner.Tests.ps1 index 5a5320ed..82ff1b7b 100644 --- a/.github/tests/Unit/WinCleaner.Tests.ps1 +++ b/.github/tests/Unit/WinCleaner.Tests.ps1 @@ -57,4 +57,45 @@ Describe 'WinCleaner — VitalExclusions' { $source = Get-Content -Path $script:ToolPath -Raw $source | Should -Match 'LocalAppData.*WinToolkit' } -} \ No newline at end of file +} + +Describe 'WinCleaner — Invoke-CommandAction displayName (regression for empty NameKey)' { + + It 'Resolves DisplayName via Get-SourceTextLoc only when NameKey is present' { + $source = Get-Content -Path $script:ToolPath -Raw + $source | Should -Match '\$displayName\s*=\s*if\s*\(\s*\$Rule\.NameKey\s*\)\s*\{' + $source | Should -Match 'Get-SourceTextLoc\s+\$Rule\.NameKey\s*\}\s*else\s*\{\s*\$Rule\.Name\s*\}' + } + + It 'Never calls Get-SourceTextLoc with a bare (unguarded) NameKey' { + # Before the fix: "$displayName = Get-SourceTextLoc $Rule.NameKey" → throws + # "Cannot bind argument to parameter 'Key' because it is an empty string" + # when a Command rule omits NameKey (e.g. the inline cleanmgr rules). + $source = Get-Content -Path $script:ToolPath -Raw + $source | Should -Not -Match '\$displayName\s*=\s*Get-SourceTextLoc\s+\$Rule\.NameKey\s*$' + } + + It 'Inline CleanMgr Command rules still expose a Name for the NameKey fallback' { + $source = Get-Content -Path $script:ToolPath -Raw + $source | Should -Match "Name\s*=\s*'Running CleanMgr with /sagerun:65'" + $source | Should -Match "Name\s*=\s*'Removing Windows\.old \(CleanMgr\)'" + } +} + +Describe 'WinCleaner — Get-LocalUserProfiles (regression for undefined function)' { + + It 'Get-LocalUserProfiles is defined by the core and callable at runtime' { + # Before the fix the function was undefined, so every per-user rule aborted + # WinCleaner with "Il termine 'Get-LocalUserProfiles' non è riconosciuto". + # It is provided by the shared core (wintoolkit-modules/40-Module.System.ps1) + # and must therefore be available after the template + tool are imported. + Get-Command Get-LocalUserProfiles -ErrorAction SilentlyContinue | Should -Not -BeNull + { Get-LocalUserProfiles } | Should -Not -Throw + } + + It 'WinCleaner references Get-LocalUserProfiles and does not define a local copy' { + $source = Get-Content -Path $script:ToolPath -Raw + $source | Should -Match 'Get-LocalUserProfiles' + $source | Should -Not -Match 'function Get-LocalUserProfiles\s*\{' + } +} diff --git a/WinToolkit.ps1 b/WinToolkit.ps1 index 136f1c95..36a15d7d 100644 --- a/WinToolkit.ps1 +++ b/WinToolkit.ps1 @@ -708,7 +708,7 @@ function Get-BitlockerStatus { return (Get-SourceTextLoc 'bitlocker.status.off') } } -function Get-SourceTextLocalUserProfiles { +function Get-LocalUserProfiles { return Get-ChildItem "C:\Users" -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -notmatch '^(Public|Default|Default User|All Users)$' } } @@ -3105,7 +3105,7 @@ function WinCleaner { } function Invoke-CommandAction { param($Rule) - $displayName = Get-SourceTextLoc $Rule.NameKey + $displayName = if ($Rule.NameKey) { Get-SourceTextLoc $Rule.NameKey } else { $Rule.Name } Clear-ProgressLine Write-StyledMessage -Type 'Info' -Text ("🚀 " + (Get-SourceTextLoc 'toolText.commandExecution0' -Args @($displayName))) try { diff --git a/tools/WinCleaner.ps1 b/tools/WinCleaner.ps1 index a9c353ec..15a5588a 100644 --- a/tools/WinCleaner.ps1 +++ b/tools/WinCleaner.ps1 @@ -71,7 +71,7 @@ function WinCleaner { function Invoke-CommandAction { param($Rule) - $displayName = Get-SourceTextLoc $Rule.NameKey + $displayName = if ($Rule.NameKey) { Get-SourceTextLoc $Rule.NameKey } else { $Rule.Name } Clear-ProgressLine Write-StyledMessage -Type 'Info' -Text ("🚀 " + (Get-SourceTextLoc 'toolText.commandExecution0' -Args @($displayName))) try { diff --git a/wintoolkit-modules/40-Module.System.ps1 b/wintoolkit-modules/40-Module.System.ps1 index 83f718c5..6b34032c 100644 --- a/wintoolkit-modules/40-Module.System.ps1 +++ b/wintoolkit-modules/40-Module.System.ps1 @@ -75,7 +75,7 @@ function Get-BitlockerStatus { } -function Get-SourceTextLocalUserProfiles { +function Get-LocalUserProfiles { <# .SYNOPSIS Restituisce le directory utente reali, escludendo i profili di sistema.