Files
Win11Debloat/Tests/Set-StoreSearchSuggestions.Tests.ps1
T

235 lines
9.7 KiB
PowerShell

BeforeAll {
function Get-UserDirectory { param($userName, $fileName) }
function Invoke-NonBlocking { param($ScriptBlock, $ArgumentList) }
function takeown { param([Parameter(ValueFromRemainingArguments)]$Arguments) }
function icacls { param([Parameter(ValueFromRemainingArguments)]$Arguments) }
function New-TestStoreDatabaseAcl {
param([object[]]$Access = @())
$acl = [PSCustomObject]@{
Access = $Access
AddedRules = [System.Collections.Generic.List[object]]::new()
RemovedRules = [System.Collections.Generic.List[object]]::new()
}
$acl | Add-Member -MemberType ScriptMethod -Name SetAccessRule -Value {
param($Rule)
$this.AddedRules.Add($Rule)
}
$acl | Add-Member -MemberType ScriptMethod -Name RemoveAccessRuleSpecific -Value {
param($Rule)
$this.RemovedRules.Add($Rule)
return $true
}
return $acl
}
. (Join-Path $PSScriptRoot '..\Scripts\Features\Set-StoreSearchSuggestions.ps1')
}
Describe 'Store-search suggestion all-user operations' {
BeforeEach {
$script:Params = @{}
Mock Get-UserDirectory { 'C:\Users\*\AppData\Local\Packages' }
Mock Get-ChildItem {
@(
[PSCustomObject]@{ FullName = 'C:\Users\Alice\AppData\Local\Packages' }
[PSCustomObject]@{ FullName = 'C:\Users\Bob\AppData\Local\Packages' }
)
}
Mock Get-StoreAppsDatabasePathForUser { 'C:\Users\Default\AppData\Local\Packages\Microsoft.WindowsStore_8wekyb3d8bbwe\LocalState\store.db' }
Mock Set-StoreSearchSuggestionsDisabled {}
Mock Set-StoreSearchSuggestionsEnabled {}
Mock Write-Warning {}
}
It 'disables suggestions for every discovered and Default profile' {
Set-StoreSearchSuggestionsDisabledForAllUsers
Should -Invoke Set-StoreSearchSuggestionsDisabled -Times 3 -Exactly
Should -Invoke Set-StoreSearchSuggestionsDisabled -Times 1 -Exactly -ParameterFilter { $StoreAppsDatabase -match 'Users\\Default\\' }
}
It 'enables suggestions for every discovered and Default profile' {
Set-StoreSearchSuggestionsEnabledForAllUsers
Should -Invoke Set-StoreSearchSuggestionsEnabled -Times 3 -Exactly
Should -Invoke Set-StoreSearchSuggestionsEnabled -Times 1 -Exactly -ParameterFilter { $StoreAppsDatabase -match 'Users\\Default\\' }
}
It 'does not add a Default profile disable operation when its Store database path cannot be resolved' {
Mock Get-StoreAppsDatabasePathForUser { $null }
Set-StoreSearchSuggestionsDisabledForAllUsers
Should -Invoke Set-StoreSearchSuggestionsDisabled -Times 2 -Exactly
}
It 'does not add a Default profile enable operation when its Store database path cannot be resolved' {
Mock Get-StoreAppsDatabasePathForUser { $null }
Set-StoreSearchSuggestionsEnabledForAllUsers
Should -Invoke Set-StoreSearchSuggestionsEnabled -Times 2 -Exactly
}
}
Describe 'Set-StoreSearchSuggestionsDisabled' {
BeforeEach {
$script:Params = @{ WhatIf = $true }
Mock Test-Path { throw 'WhatIf should return before filesystem access.' }
Mock Get-Acl { throw 'WhatIf should return before ACL access.' }
Mock Set-Acl { throw 'WhatIf should return before ACL access.' }
Mock Write-Host {}
}
It 'does not touch the filesystem in WhatIf mode' {
Set-StoreSearchSuggestionsDisabled -StoreAppsDatabase 'C:\Users\Alice\AppData\Local\Packages\store.db'
Should -Invoke Test-Path -Times 0 -Exactly
Should -Invoke Get-Acl -Times 0 -Exactly
Should -Invoke Set-Acl -Times 0 -Exactly
}
It 'creates a missing database and parent directory before applying the deny rule' {
$script:Params = @{}
$acl = New-TestStoreDatabaseAcl
Mock Test-Path { $false }
Mock New-Item {}
Mock Get-Acl { $acl }
Mock Set-Acl {}
Set-StoreSearchSuggestionsDisabled -StoreAppsDatabase 'C:\Users\Alice\AppData\Local\Packages\store.db'
Should -Invoke New-Item -Times 2 -Exactly
Should -Invoke New-Item -Times 1 -Exactly -ParameterFilter { $ItemType -eq 'Directory' }
Should -Invoke New-Item -Times 1 -Exactly -ParameterFilter { $ItemType -eq 'File' }
Should -Invoke New-Item -Times 1 -Exactly -ParameterFilter { $Path -eq 'C:\Users\Alice\AppData\Local\Packages' -and $ItemType -eq 'Directory' -and $Force }
Should -Invoke New-Item -Times 1 -Exactly -ParameterFilter { $Path -eq 'C:\Users\Alice\AppData\Local\Packages\store.db' -and $ItemType -eq 'File' -and $Force }
Should -Invoke Set-Acl -Times 1 -Exactly -ParameterFilter { $Path -eq 'C:\Users\Alice\AppData\Local\Packages\store.db' -and $AclObject -eq $acl }
$acl.AddedRules | Should -HaveCount 1
}
It 'updates the ACL without creating anything when the database already exists' {
$script:Params = @{}
$acl = New-TestStoreDatabaseAcl
Mock Test-Path { $true }
Mock New-Item { throw 'Existing database must not be recreated.' }
Mock Get-Acl { $acl }
Mock Set-Acl {}
Set-StoreSearchSuggestionsDisabled -StoreAppsDatabase 'C:\Users\Alice\AppData\Local\Packages\store.db'
Should -Invoke New-Item -Times 0 -Exactly
Should -Invoke Get-Acl -Times 1 -Exactly
Should -Invoke Set-Acl -Times 1 -Exactly
$acl.AddedRules | Should -HaveCount 1
}
It 'warns and does not report success when reading the ACL fails' {
$script:Params = @{}
Mock Test-Path { $true }
Mock Get-Acl { throw 'access denied' }
Mock Set-Acl { throw 'ACL must not be written after a read failure.' }
Mock Write-Warning {}
Set-StoreSearchSuggestionsDisabled -StoreAppsDatabase 'C:\Users\Alice\AppData\Local\Packages\store.db'
Should -Invoke Write-Warning -Times 1 -Exactly
Should -Invoke Write-Host -Times 0 -Exactly -ParameterFilter { $Object -like 'Disabled Microsoft Store search suggestions*' }
Should -Invoke Set-Acl -Times 0 -Exactly
}
It 'warns and does not report success when writing the ACL fails' {
$script:Params = @{}
$acl = New-TestStoreDatabaseAcl
Mock Test-Path { $true }
Mock Get-Acl { $acl }
Mock Set-Acl { throw 'access denied' }
Mock Write-Warning {}
Set-StoreSearchSuggestionsDisabled -StoreAppsDatabase 'C:\Users\Alice\AppData\Local\Packages\store.db'
Should -Invoke Write-Warning -Times 1 -Exactly
Should -Invoke Write-Host -Times 0 -Exactly -ParameterFilter { $Object -like 'Disabled Microsoft Store search suggestions*' }
}
}
Describe 'Set-StoreSearchSuggestionsEnabled' {
BeforeEach {
$script:Params = @{}
Mock Test-Path { $false }
Mock Get-Acl { throw 'A missing database should return before ACL access.' }
Mock Remove-Item { throw 'A missing database should not be removed.' }
Mock Write-Host {}
}
It 'does nothing when the Store database does not exist' {
Set-StoreSearchSuggestionsEnabled -StoreAppsDatabase 'C:\Users\Alice\AppData\Local\Packages\store.db'
Should -Invoke Get-Acl -Times 0 -Exactly
Should -Invoke Remove-Item -Times 0 -Exactly
}
It 'does not touch an existing database in WhatIf mode' {
$script:Params = @{ WhatIf = $true }
Mock Test-Path { throw 'WhatIf should return before filesystem access.' }
Mock takeown { throw 'WhatIf should not take ownership.' }
Mock icacls { throw 'WhatIf should not change ACLs.' }
Set-StoreSearchSuggestionsEnabled -StoreAppsDatabase 'C:\Users\Alice\AppData\Local\Packages\store.db'
Should -Invoke Test-Path -Times 0 -Exactly
Should -Invoke takeown -Times 0 -Exactly
Should -Invoke icacls -Times 0 -Exactly
}
It 'normalizes the ACL and removes an existing database' {
$acl = New-TestStoreDatabaseAcl
Mock Test-Path { $true }
Mock takeown {}
Mock icacls {}
Mock Get-Acl { $acl }
Mock Set-Acl {}
Mock Remove-Item {}
Set-StoreSearchSuggestionsEnabled -StoreAppsDatabase 'C:\Users\Alice\AppData\Local\Packages\store.db'
Should -Invoke takeown -Times 1 -Exactly
Should -Invoke icacls -Times 1 -Exactly
Should -Invoke Get-Acl -Times 1 -Exactly
Should -Invoke Set-Acl -Times 1 -Exactly
Should -Invoke Remove-Item -Times 1 -Exactly -ParameterFilter { $Path -eq 'C:\Users\Alice\AppData\Local\Packages\store.db' -and $Force -and $ErrorAction -eq 'Stop' }
}
It 'continues removing an existing database when ACL normalization fails' {
Mock Test-Path { $true }
Mock takeown {}
Mock icacls {}
Mock Get-Acl { throw 'access denied' }
Mock Set-Acl { throw 'Set-Acl must not run after Get-Acl fails.' }
Mock Remove-Item {}
Mock Write-Warning {}
Set-StoreSearchSuggestionsEnabled -StoreAppsDatabase 'C:\Users\Alice\AppData\Local\Packages\store.db'
Should -Invoke Write-Warning -Times 1 -Exactly
Should -Invoke Set-Acl -Times 0 -Exactly
Should -Invoke Remove-Item -Times 1 -Exactly
}
It 'throws a contextual error when the database cannot be removed' {
$acl = New-TestStoreDatabaseAcl
Mock Test-Path { $true }
Mock takeown {}
Mock icacls {}
Mock Get-Acl { $acl }
Mock Set-Acl {}
Mock Remove-Item { throw 'database is locked' }
{
Set-StoreSearchSuggestionsEnabled -StoreAppsDatabase 'C:\Users\Alice\AppData\Local\Packages\store.db'
} | Should -Throw '*Failed to remove*database is locked*'
}
}