mirror of
https://github.com/Raphire/Win11Debloat.git
synced 2026-08-22 07:36:25 +00:00
fix: match tweak presets and app-removal scope by stable ID instead of translatable text (#737)
This commit is contained in:
@@ -2,50 +2,62 @@
|
||||
"Version": "1.0",
|
||||
"Categories": [
|
||||
{
|
||||
"CategoryId": "PrivacySuggestedContent",
|
||||
"Name": "Privacy & Suggested Content",
|
||||
"Icon": ""
|
||||
},
|
||||
{
|
||||
"CategoryId": "System",
|
||||
"Name": "System",
|
||||
"Icon": ""
|
||||
},
|
||||
{
|
||||
"CategoryId": "StartMenuSearch",
|
||||
"Name": "Start Menu & Search",
|
||||
"Icon": ""
|
||||
},
|
||||
{
|
||||
"CategoryId": "AI",
|
||||
"Name": "AI",
|
||||
"Icon": ""
|
||||
},
|
||||
{
|
||||
"CategoryId": "WindowsUpdate",
|
||||
"Name": "Windows Update",
|
||||
"Icon": ""
|
||||
},
|
||||
{
|
||||
"CategoryId": "Taskbar",
|
||||
"Name": "Taskbar",
|
||||
"Icon": ""
|
||||
},
|
||||
{
|
||||
"CategoryId": "Appearance",
|
||||
"Name": "Appearance",
|
||||
"Icon": ""
|
||||
},
|
||||
{
|
||||
"CategoryId": "FileExplorer",
|
||||
"Name": "File Explorer",
|
||||
"Icon": ""
|
||||
},
|
||||
{
|
||||
"CategoryId": "Gaming",
|
||||
"Name": "Gaming",
|
||||
"Icon": ""
|
||||
},
|
||||
{
|
||||
"CategoryId": "MultiTasking",
|
||||
"Name": "Multi-tasking",
|
||||
"Icon": ""
|
||||
},
|
||||
{
|
||||
"CategoryId": "OptionalWindowsFeatures",
|
||||
"Name": "Optional Windows Features",
|
||||
"Icon": ""
|
||||
},
|
||||
{
|
||||
"CategoryId": "Other",
|
||||
"Name": "Other",
|
||||
"Icon": ""
|
||||
}
|
||||
|
||||
@@ -174,6 +174,10 @@ function Update-AppSelectionStatus {
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Updates the app-removal scope description to match the selected ComboBoxItem.
|
||||
#>
|
||||
function Update-AppRemovalScopeDescription {
|
||||
param(
|
||||
[System.Windows.Controls.ComboBox]$AppRemovalScopeCombo,
|
||||
@@ -182,20 +186,58 @@ function Update-AppRemovalScopeDescription {
|
||||
|
||||
$selectedItem = $AppRemovalScopeCombo.SelectedItem
|
||||
if ($selectedItem) {
|
||||
switch ($selectedItem.Content) {
|
||||
"All users" {
|
||||
# Content is the display text and will change once translated; Name is stable.
|
||||
switch ($selectedItem.Name) {
|
||||
"AppRemovalScopeAllUsers" {
|
||||
$AppRemovalScopeDescription.Text = "Apps will be removed for all users and from the Windows image to prevent reinstallation for new users."
|
||||
}
|
||||
"Current user only" {
|
||||
"AppRemovalScopeCurrentUser" {
|
||||
$AppRemovalScopeDescription.Text = "Apps will only be removed for the current user."
|
||||
}
|
||||
"Target user only" {
|
||||
"AppRemovalScopeTargetUser" {
|
||||
$AppRemovalScopeDescription.Text = "Apps will only be removed for the specified target user."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Tests whether the app-removal scope combo is currently set to "Target user only".
|
||||
#>
|
||||
function Test-AppRemovalScopeTargetsOtherUser {
|
||||
param(
|
||||
[System.Windows.Controls.ComboBox]$AppRemovalScopeCombo
|
||||
)
|
||||
|
||||
return ($AppRemovalScopeCombo -and $AppRemovalScopeCombo.SelectedItem -and $AppRemovalScopeCombo.SelectedItem.Name -eq 'AppRemovalScopeTargetUser')
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Resolves the -AppRemovalTarget value for the selected app-removal scope.
|
||||
#>
|
||||
function Get-AppRemovalScopeTarget {
|
||||
param(
|
||||
[System.Windows.Controls.ComboBox]$AppRemovalScopeCombo,
|
||||
[System.Windows.Controls.TextBox]$OtherUsernameTextBox
|
||||
)
|
||||
|
||||
$selectedItem = $AppRemovalScopeCombo.SelectedItem
|
||||
if (-not $selectedItem) { return $null }
|
||||
|
||||
if (Test-AppRemovalScopeTargetsOtherUser -AppRemovalScopeCombo $AppRemovalScopeCombo) {
|
||||
return $OtherUsernameTextBox.Text.Trim()
|
||||
}
|
||||
|
||||
switch ($selectedItem.Name) {
|
||||
"AppRemovalScopeAllUsers" { return 'AllUsers' }
|
||||
"AppRemovalScopeCurrentUser" { return 'CurrentUser' }
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Invoke-AppPreset {
|
||||
param(
|
||||
[System.Windows.Controls.Panel]$AppsPanel,
|
||||
|
||||
@@ -219,8 +219,8 @@ function Get-TweakPresetControlMap {
|
||||
.PARAMETER Window
|
||||
The window that owns the visible tweak controls.
|
||||
|
||||
.PARAMETER Category
|
||||
The category whose mapped controls are included.
|
||||
.PARAMETER CategoryId
|
||||
The stable CategoryId (from Features.json) whose mapped controls are included.
|
||||
|
||||
.OUTPUTS
|
||||
System.Collections.Hashtable. Control metadata keyed by control name.
|
||||
@@ -228,7 +228,7 @@ function Get-TweakPresetControlMap {
|
||||
function Get-CategoryTweakPresetMap {
|
||||
param(
|
||||
[System.Windows.Window]$Window,
|
||||
[string]$Category
|
||||
[string]$CategoryId
|
||||
)
|
||||
|
||||
$presetMap = @{}
|
||||
@@ -236,7 +236,7 @@ function Get-CategoryTweakPresetMap {
|
||||
|
||||
foreach ($controlName in $script:UiControlMappings.Keys) {
|
||||
$mapping = $script:UiControlMappings[$controlName]
|
||||
if ($mapping.Category -ne $Category) { continue }
|
||||
if ($mapping.CategoryId -ne $CategoryId) { continue }
|
||||
|
||||
$control = $Window.FindName($controlName)
|
||||
if (-not $control -or $control.Visibility -ne 'Visible') { continue }
|
||||
@@ -403,8 +403,8 @@ function Initialize-TweakPresetSources {
|
||||
|
||||
$script:DefaultTweakPresetMap = Get-TweakPresetControlMap -Window $Window -SettingsJson $DefaultSettingsJson
|
||||
$script:LastUsedTweakPresetMap = Get-TweakPresetControlMap -Window $Window -SettingsJson $LastUsedSettingsJson
|
||||
$script:PrivacyTweakPresetMap = Get-CategoryTweakPresetMap -Window $Window -Category 'Privacy & Suggested Content'
|
||||
$script:AITweakPresetMap = Get-CategoryTweakPresetMap -Window $Window -Category 'AI'
|
||||
$script:PrivacyTweakPresetMap = Get-CategoryTweakPresetMap -Window $Window -CategoryId 'PrivacySuggestedContent'
|
||||
$script:AITweakPresetMap = Get-CategoryTweakPresetMap -Window $Window -CategoryId 'AI'
|
||||
|
||||
$presetLastUsedTweaksBtn = $Window.FindName('PresetLastUsedTweaksBtn')
|
||||
if ($presetLastUsedTweaksBtn) {
|
||||
@@ -478,11 +478,14 @@ function Test-OtherUsername {
|
||||
[System.Windows.Window]$Window,
|
||||
[System.Windows.Controls.ComboBox]$UserSelectionCombo,
|
||||
[System.Windows.Controls.TextBox]$OtherUsernameTextBox,
|
||||
[System.Windows.Controls.TextBlock]$UsernameValidationMessage
|
||||
[System.Windows.Controls.TextBlock]$UsernameValidationMessage,
|
||||
[System.Windows.Controls.ComboBox]$AppRemovalScopeCombo
|
||||
)
|
||||
|
||||
# Only validate if "Other User" is selected
|
||||
if ($UserSelectionCombo.SelectedIndex -ne 1) {
|
||||
# Only validate if "Other User" is the deployment target, or "Target user only" is the app-removal scope
|
||||
$isOtherUserSelected = ($UserSelectionCombo.SelectedIndex -eq 1)
|
||||
$isAppRemovalTargetUserSelected = Test-AppRemovalScopeTargetsOtherUser -AppRemovalScopeCombo $AppRemovalScopeCombo
|
||||
if (-not $isOtherUserSelected -and -not $isAppRemovalTargetUserSelected) {
|
||||
return $true
|
||||
}
|
||||
|
||||
|
||||
@@ -234,8 +234,17 @@ function New-DynamicTweakControls {
|
||||
foreach ($c in $featuresJson.Categories) {
|
||||
$categoryName = if ($c -is [string]) { $c } else { $c.Name }
|
||||
if ($categoriesPresent.ContainsKey($categoryName)) {
|
||||
# Store the full category object (or create one with default icon for string categories)
|
||||
$categoryObj = if ($c -is [string]) { @{Name = $c; Icon = '' } } else { $c }
|
||||
# Store the full category object (or create one with default icon for string categories).
|
||||
# A category without its own CategoryId falls back to its Name, same as before CategoryId existed.
|
||||
$categoryObj = if ($c -is [string]) {
|
||||
@{Name = $c; CategoryId = $c; Icon = '' }
|
||||
}
|
||||
elseif (-not $c.CategoryId) {
|
||||
@{Name = $c.Name; CategoryId = $c.Name; Icon = $c.Icon }
|
||||
}
|
||||
else {
|
||||
$c
|
||||
}
|
||||
$orderedCategories += $categoryObj
|
||||
}
|
||||
}
|
||||
@@ -243,7 +252,7 @@ function New-DynamicTweakControls {
|
||||
else {
|
||||
# For backward compatibility, create category objects from keys
|
||||
foreach ($catName in $categoriesPresent.Keys) {
|
||||
$orderedCategories += @{Name = $catName; Icon = '' }
|
||||
$orderedCategories += @{Name = $catName; CategoryId = $catName; Icon = '' }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,6 +264,7 @@ function New-DynamicTweakControls {
|
||||
|
||||
foreach ($categoryObj in $orderedCategories) {
|
||||
$categoryName = $categoryObj.Name
|
||||
$categoryId = $categoryObj.CategoryId
|
||||
|
||||
# Card is created lazily on the first rendered item
|
||||
$panel = $null
|
||||
@@ -359,7 +369,7 @@ function New-DynamicTweakControls {
|
||||
try { $lblBorderObj = $Window.FindName("$comboName`_LabelBorder") } catch {}
|
||||
if ($lblBorderObj) { $lblBorderObj.ToolTip = $tipBlock }
|
||||
}
|
||||
$script:UiControlMappings[$comboName] = @{ Type = 'feature'; FeatureId = $soleFeature.FeatureId; Label = $soleFeature.Label; Category = $categoryName }
|
||||
$script:UiControlMappings[$comboName] = @{ Type = 'feature'; FeatureId = $soleFeature.FeatureId; Label = $soleFeature.Label; Category = $categoryName; CategoryId = $categoryId }
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -379,7 +389,7 @@ function New-DynamicTweakControls {
|
||||
try { $lblBorderObj = $Window.FindName("$comboName`_LabelBorder") } catch {}
|
||||
if ($lblBorderObj) { $lblBorderObj.ToolTip = $tipBlock }
|
||||
}
|
||||
$script:UiControlMappings[$comboName] = @{ Type = 'group'; Values = $filteredValues; Label = $group.Label; Category = $categoryName }
|
||||
$script:UiControlMappings[$comboName] = @{ Type = 'group'; Values = $filteredValues; Label = $group.Label; Category = $categoryName; CategoryId = $categoryId }
|
||||
}
|
||||
elseif ($item.Type -eq 'feature') {
|
||||
$feature = $item.Data
|
||||
@@ -406,7 +416,7 @@ function New-DynamicTweakControls {
|
||||
try { $lblBorderObj = $Window.FindName("$comboName`_LabelBorder") } catch {}
|
||||
if ($lblBorderObj) { $lblBorderObj.ToolTip = $tipBlock }
|
||||
}
|
||||
$script:UiControlMappings[$comboName] = @{ Type = 'feature'; FeatureId = $feature.FeatureId; Label = $feature.Label; Category = $categoryName }
|
||||
$script:UiControlMappings[$comboName] = @{ Type = 'feature'; FeatureId = $feature.FeatureId; Label = $feature.Label; Category = $categoryName; CategoryId = $categoryId }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,6 +577,7 @@ function Show-MainWindow {
|
||||
# ---- App removal scope combo ----
|
||||
$appRemovalScopeCombo.Add_SelectionChanged({
|
||||
Update-AppRemovalScopeDescription -AppRemovalScopeCombo $appRemovalScopeCombo -AppRemovalScopeDescription $appRemovalScopeDescription
|
||||
Test-OtherUsername -Window $window -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -UsernameValidationMessage $usernameValidationMessage -AppRemovalScopeCombo $appRemovalScopeCombo | Out-Null
|
||||
})
|
||||
|
||||
# ---- Other username text box ----
|
||||
@@ -588,12 +589,12 @@ function Show-MainWindow {
|
||||
$usernameTextBoxPlaceholder.Visibility = 'Collapsed'
|
||||
}
|
||||
Update-UserSelectionDescription -Window $window -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -UserSelectionDescription $userSelectionDescription
|
||||
Test-OtherUsername -Window $window -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -UsernameValidationMessage $usernameValidationMessage | Out-Null
|
||||
Test-OtherUsername -Window $window -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -UsernameValidationMessage $usernameValidationMessage -AppRemovalScopeCombo $appRemovalScopeCombo | Out-Null
|
||||
})
|
||||
|
||||
# ---- Validate target user helper ----
|
||||
$ensureValidTargetUserOrWarn = {
|
||||
if (-not (Test-OtherUsername -Window $window -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -UsernameValidationMessage $usernameValidationMessage)) {
|
||||
if (-not (Test-OtherUsername -Window $window -UserSelectionCombo $userSelectionCombo -OtherUsernameTextBox $otherUsernameTextBox -UsernameValidationMessage $usernameValidationMessage -AppRemovalScopeCombo $appRemovalScopeCombo)) {
|
||||
$validationMessage = if (-not [string]::IsNullOrWhiteSpace($usernameValidationMessage.Text)) {
|
||||
$usernameValidationMessage.Text
|
||||
}
|
||||
@@ -672,13 +673,9 @@ function Show-MainWindow {
|
||||
Add-Parameter 'RemoveApps'
|
||||
Add-Parameter 'Apps' ($selectedApps -join ',')
|
||||
|
||||
$selectedScopeItem = $appRemovalScopeCombo.SelectedItem
|
||||
if ($selectedScopeItem) {
|
||||
switch ($selectedScopeItem.Content) {
|
||||
"All users" { Add-Parameter 'AppRemovalTarget' 'AllUsers' }
|
||||
"Current user only" { Add-Parameter 'AppRemovalTarget' 'CurrentUser' }
|
||||
"Target user only" { Add-Parameter 'AppRemovalTarget' ($otherUsernameTextBox.Text.Trim()) }
|
||||
}
|
||||
$scopeTarget = Get-AppRemovalScopeTarget -AppRemovalScopeCombo $appRemovalScopeCombo -OtherUsernameTextBox $otherUsernameTextBox
|
||||
if ($scopeTarget) {
|
||||
Add-Parameter 'AppRemovalTarget' $scopeTarget
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,14 +117,27 @@ Describe 'Get-PendingTweakActions' {
|
||||
$checkBox = New-Object System.Windows.Controls.CheckBox
|
||||
$checkBox.Visibility = 'Visible'
|
||||
$window.RegisterName('DisableTelemetryCheckBox', $checkBox)
|
||||
$script:UiControlMappings = @{ DisableTelemetryCheckBox = [PSCustomObject]@{ Category = 'Privacy'; Type = 'feature'; FeatureId = 'DisableTelemetry' } }
|
||||
$script:UiControlMappings = @{ DisableTelemetryCheckBox = [PSCustomObject]@{ Category = 'Privacy & Suggested Content'; CategoryId = 'PrivacySuggestedContent'; Type = 'feature'; FeatureId = 'DisableTelemetry' } }
|
||||
|
||||
$map = Get-CategoryTweakPresetMap -Window $window -Category 'Privacy'
|
||||
$map = Get-CategoryTweakPresetMap -Window $window -CategoryId 'PrivacySuggestedContent'
|
||||
|
||||
$map['DisableTelemetryCheckBox'].ControlType | Should -Be 'CheckBox'
|
||||
$map['DisableTelemetryCheckBox'].DesiredValue | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'matches a mapping whose CategoryId fell back to its Name, for a category missing CategoryId' {
|
||||
$window = New-TestWindow
|
||||
$checkBox = New-Object System.Windows.Controls.CheckBox
|
||||
$checkBox.Visibility = 'Visible'
|
||||
$window.RegisterName('LegacyCheckBox', $checkBox)
|
||||
# New-DynamicTweakControls falls back to Name when a category has no CategoryId of its own.
|
||||
$script:UiControlMappings = @{ LegacyCheckBox = [PSCustomObject]@{ Category = 'Legacy Category'; CategoryId = 'Legacy Category'; Type = 'feature'; FeatureId = 'SomeFeature' } }
|
||||
|
||||
$map = Get-CategoryTweakPresetMap -Window $window -CategoryId 'Legacy Category'
|
||||
|
||||
$map['LegacyCheckBox'].ControlType | Should -Be 'CheckBox'
|
||||
}
|
||||
|
||||
It 'updates navigation visibility and progress indicators for an interior tab' {
|
||||
$window = New-TestWindow
|
||||
$tabControl = New-Object System.Windows.Controls.TabControl
|
||||
@@ -142,6 +155,86 @@ Describe 'Get-PendingTweakActions' {
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Update-AppRemovalScopeDescription' {
|
||||
It 'matches on the ComboBoxItem Name rather than its (translatable) Content for <Name>' -ForEach @(
|
||||
@{ Name = 'AppRemovalScopeAllUsers'; ExpectedText = 'Apps will be removed for all users and from the Windows image to prevent reinstallation for new users.' }
|
||||
@{ Name = 'AppRemovalScopeCurrentUser'; ExpectedText = 'Apps will only be removed for the current user.' }
|
||||
@{ Name = 'AppRemovalScopeTargetUser'; ExpectedText = 'Apps will only be removed for the specified target user.' }
|
||||
) {
|
||||
$combo = New-Object System.Windows.Controls.ComboBox
|
||||
$item = New-Object System.Windows.Controls.ComboBoxItem
|
||||
$item.Name = $Name
|
||||
$item.Content = 'Texto traducido'
|
||||
$combo.Items.Add($item) | Out-Null
|
||||
$combo.SelectedItem = $item
|
||||
$description = New-Object System.Windows.Controls.TextBlock
|
||||
|
||||
Update-AppRemovalScopeDescription -AppRemovalScopeCombo $combo -AppRemovalScopeDescription $description
|
||||
|
||||
$description.Text | Should -Be $ExpectedText
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Get-AppRemovalScopeTarget' {
|
||||
It 'matches on the ComboBoxItem Name rather than its (translatable) Content for <Name>' -ForEach @(
|
||||
@{ Name = 'AppRemovalScopeAllUsers'; ExpectedTarget = 'AllUsers' }
|
||||
@{ Name = 'AppRemovalScopeCurrentUser'; ExpectedTarget = 'CurrentUser' }
|
||||
) {
|
||||
$combo = New-Object System.Windows.Controls.ComboBox
|
||||
$item = New-Object System.Windows.Controls.ComboBoxItem
|
||||
$item.Name = $Name
|
||||
$item.Content = 'Texto traducido'
|
||||
$combo.Items.Add($item) | Out-Null
|
||||
$combo.SelectedItem = $item
|
||||
$usernameBox = New-Object System.Windows.Controls.TextBox
|
||||
|
||||
Get-AppRemovalScopeTarget -AppRemovalScopeCombo $combo -OtherUsernameTextBox $usernameBox | Should -Be $ExpectedTarget
|
||||
}
|
||||
|
||||
It 'returns the trimmed username for the target-user scope' {
|
||||
$combo = New-Object System.Windows.Controls.ComboBox
|
||||
$item = New-Object System.Windows.Controls.ComboBoxItem
|
||||
$item.Name = 'AppRemovalScopeTargetUser'
|
||||
$item.Content = 'Texto traducido'
|
||||
$combo.Items.Add($item) | Out-Null
|
||||
$combo.SelectedItem = $item
|
||||
$usernameBox = New-Object System.Windows.Controls.TextBox
|
||||
$usernameBox.Text = ' jdoe '
|
||||
|
||||
Get-AppRemovalScopeTarget -AppRemovalScopeCombo $combo -OtherUsernameTextBox $usernameBox | Should -Be 'jdoe'
|
||||
}
|
||||
|
||||
It 'returns null when nothing is selected' {
|
||||
$combo = New-Object System.Windows.Controls.ComboBox
|
||||
$usernameBox = New-Object System.Windows.Controls.TextBox
|
||||
|
||||
Get-AppRemovalScopeTarget -AppRemovalScopeCombo $combo -OtherUsernameTextBox $usernameBox | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'returns null for an unrecognized ComboBoxItem Name' {
|
||||
$combo = New-Object System.Windows.Controls.ComboBox
|
||||
$item = New-Object System.Windows.Controls.ComboBoxItem
|
||||
$item.Name = 'SomeUnrelatedControl'
|
||||
$combo.Items.Add($item) | Out-Null
|
||||
$combo.SelectedItem = $item
|
||||
$usernameBox = New-Object System.Windows.Controls.TextBox
|
||||
|
||||
Get-AppRemovalScopeTarget -AppRemovalScopeCombo $combo -OtherUsernameTextBox $usernameBox | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'returns an empty string for the target-user scope when the username is blank' {
|
||||
$combo = New-Object System.Windows.Controls.ComboBox
|
||||
$item = New-Object System.Windows.Controls.ComboBoxItem
|
||||
$item.Name = 'AppRemovalScopeTargetUser'
|
||||
$combo.Items.Add($item) | Out-Null
|
||||
$combo.SelectedItem = $item
|
||||
$usernameBox = New-Object System.Windows.Controls.TextBox
|
||||
$usernameBox.Text = ' '
|
||||
|
||||
Get-AppRemovalScopeTarget -AppRemovalScopeCombo $combo -OtherUsernameTextBox $usernameBox | Should -BeExactly ''
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Set-WindowThemeResources' {
|
||||
It 'populates themed resources and selects the Windows 11 icon font' {
|
||||
$window = New-TestWindow
|
||||
|
||||
@@ -1,6 +1,40 @@
|
||||
BeforeAll {
|
||||
Add-Type -AssemblyName PresentationFramework
|
||||
function Test-TargetUserName { param($UserName) }
|
||||
. (Join-Path $PSScriptRoot '..\Scripts\GUI\MainWindow-AppSelection.ps1')
|
||||
. (Join-Path $PSScriptRoot '..\Scripts\GUI\MainWindow-Deployment.ps1')
|
||||
. (Join-Path $PSScriptRoot '..\Scripts\GUI\Get-SystemUsesDarkMode.ps1')
|
||||
|
||||
function New-TestWindow {
|
||||
$window = New-Object System.Windows.Window
|
||||
$window.Resources['ValidationErrorColor'] = [System.Windows.Media.Brushes]::Red
|
||||
$window.Resources['ValidationSuccessColor'] = [System.Windows.Media.Brushes]::Green
|
||||
return $window
|
||||
}
|
||||
|
||||
function New-UserSelectionCombo {
|
||||
param([int]$SelectedIndex = 0)
|
||||
|
||||
$combo = New-Object System.Windows.Controls.ComboBox
|
||||
'Current User', 'Other User', 'Windows Default User (Sysprep)' | ForEach-Object {
|
||||
$combo.Items.Add((New-Object System.Windows.Controls.ComboBoxItem -Property @{ Content = $_ })) | Out-Null
|
||||
}
|
||||
$combo.SelectedIndex = $SelectedIndex
|
||||
return $combo
|
||||
}
|
||||
|
||||
function New-AppRemovalScopeCombo {
|
||||
param([string]$SelectedItemName)
|
||||
|
||||
$combo = New-Object System.Windows.Controls.ComboBox
|
||||
if ($SelectedItemName) {
|
||||
$item = New-Object System.Windows.Controls.ComboBoxItem
|
||||
$item.Name = $SelectedItemName
|
||||
$combo.Items.Add($item) | Out-Null
|
||||
$combo.SelectedItem = $item
|
||||
}
|
||||
return $combo
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Get-UndoFeatureLabel' {
|
||||
@@ -31,3 +65,44 @@ Describe 'Get-UndoFeatureLabel' {
|
||||
Get-SystemUsesDarkMode | Should -BeFalse
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Test-OtherUsername' {
|
||||
It 'skips validation when neither the deployment target nor the app-removal scope needs a username' {
|
||||
Mock Test-TargetUserName { [PSCustomObject]@{ IsValid = $false; Message = 'unused' } }
|
||||
$window = New-TestWindow
|
||||
$userCombo = New-UserSelectionCombo -SelectedIndex 0
|
||||
$usernameBox = New-Object System.Windows.Controls.TextBox
|
||||
$message = New-Object System.Windows.Controls.TextBlock
|
||||
$scopeCombo = New-AppRemovalScopeCombo -SelectedItemName 'AppRemovalScopeAllUsers'
|
||||
|
||||
Test-OtherUsername -Window $window -UserSelectionCombo $userCombo -OtherUsernameTextBox $usernameBox -UsernameValidationMessage $message -AppRemovalScopeCombo $scopeCombo | Should -BeTrue
|
||||
Should -Invoke Test-TargetUserName -Times 0 -Exactly
|
||||
}
|
||||
|
||||
It 'validates when the deployment target is Other User' {
|
||||
Mock Test-TargetUserName { [PSCustomObject]@{ IsValid = $false; Message = 'Please enter a username' } }
|
||||
$window = New-TestWindow
|
||||
$userCombo = New-UserSelectionCombo -SelectedIndex 1
|
||||
$usernameBox = New-Object System.Windows.Controls.TextBox
|
||||
$usernameBox.Text = ''
|
||||
$message = New-Object System.Windows.Controls.TextBlock
|
||||
|
||||
Test-OtherUsername -Window $window -UserSelectionCombo $userCombo -OtherUsernameTextBox $usernameBox -UsernameValidationMessage $message | Should -BeFalse
|
||||
}
|
||||
|
||||
It 'validates when the app-removal scope is Target user only, even if the deployment target is not Other User' {
|
||||
$window = New-TestWindow
|
||||
$userCombo = New-UserSelectionCombo -SelectedIndex 0
|
||||
$usernameBox = New-Object System.Windows.Controls.TextBox
|
||||
$usernameBox.Text = ' '
|
||||
$message = New-Object System.Windows.Controls.TextBlock
|
||||
$scopeCombo = New-AppRemovalScopeCombo -SelectedItemName 'AppRemovalScopeTargetUser'
|
||||
|
||||
Mock Test-TargetUserName { [PSCustomObject]@{ IsValid = $false; Message = 'Please enter a username' } }
|
||||
Test-OtherUsername -Window $window -UserSelectionCombo $userCombo -OtherUsernameTextBox $usernameBox -UsernameValidationMessage $message -AppRemovalScopeCombo $scopeCombo | Should -BeFalse
|
||||
|
||||
$usernameBox.Text = 'jdoe'
|
||||
Mock Test-TargetUserName { [PSCustomObject]@{ IsValid = $true; Message = 'User found: jdoe' } }
|
||||
Test-OtherUsername -Window $window -UserSelectionCombo $userCombo -OtherUsernameTextBox $usernameBox -UsernameValidationMessage $message -AppRemovalScopeCombo $scopeCombo | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user