mirror of
https://github.com/ScoopInstaller/Scoop.git
synced 2025-10-30 06:07:56 +00:00
refactor: Remove deprecated install_app tests and enhance Get-HistoricalManifestFromDB for exact version matching
This commit is contained in:
@@ -12,42 +12,6 @@ BeforeAll {
|
||||
. "$PSScriptRoot\..\lib\autoupdate.ps1"
|
||||
. "$PSScriptRoot\..\lib\psmodules.ps1"
|
||||
}
|
||||
Describe 'install_app' -Tag 'Scoop' {
|
||||
BeforeAll {
|
||||
# Mock all required functions and external dependencies
|
||||
Mock Get-Manifest { return @('testapp', @{ version = '1.0.0' }, 'testbucket', $null) }
|
||||
Mock Get-SupportedArchitecture { return '64bit' }
|
||||
Mock ensure { return "C:\test\dir" }
|
||||
Mock versiondir { return "C:\test\dir" }
|
||||
Mock persistdir { return "C:\test\persist" }
|
||||
Mock usermanifestsdir { return "C:\test\manifests" }
|
||||
Mock ensure_install_dir_not_in_path {}
|
||||
Mock link_current { return "C:\test\dir" }
|
||||
Mock create_shims {}
|
||||
Mock create_startmenu_shortcuts {}
|
||||
Mock Invoke-AutoUpdate { return "C:\temp\manifests\testapp.json" }
|
||||
Mock Get-ScoopDBItem { return [PSCustomObject]@{ Rows = @() } }
|
||||
Mock install_psmodule {}
|
||||
Mock env_add_path {}
|
||||
Mock env_set {}
|
||||
Mock persist_data {}
|
||||
Mock persist_permission {}
|
||||
Mock save_installed_manifest {}
|
||||
Mock save_install_info {}
|
||||
Mock show_notes {}
|
||||
Mock Write-Output {}
|
||||
Mock success {}
|
||||
}
|
||||
It 'should handle try-catch block successfully' {
|
||||
Mock Invoke-ScoopDownload { "file.txt" }
|
||||
Mock Invoke-Extraction {}
|
||||
Mock Invoke-HookScript {}
|
||||
Mock Invoke-Installer {}
|
||||
{ install_app 'testapp' '64bit' $false $false } | Should -Not -Throw
|
||||
Should -Invoke -CommandName Invoke-ScoopDownload -Times 1
|
||||
Should -Invoke -CommandName Invoke-Extraction -Times 1
|
||||
}
|
||||
}
|
||||
Describe 'appname_from_url' -Tag 'Scoop' {
|
||||
It 'should extract the correct name' {
|
||||
appname_from_url 'https://example.org/directory/foobar.json' | Should -Be 'foobar'
|
||||
@@ -172,14 +136,27 @@ Describe 'Get-HistoricalManifestFromDB' -Tag 'Scoop' {
|
||||
}
|
||||
It 'should return manifest for exact version match' {
|
||||
Mock Get-ScoopDBItem {
|
||||
$mockRow = [PSCustomObject]@{ manifest = '{"version": "1.0.0", "description": "Test app"}'; version = '1.0.0' }
|
||||
return [PSCustomObject]@{ Rows = @($mockRow) }
|
||||
param($Name, $Bucket, $Version)
|
||||
# Ensure Get-ScoopDBItem only supports exact matches
|
||||
if ($Version -eq '1.0.0') {
|
||||
$mockRow = [PSCustomObject]@{ manifest = '{"version": "1.0.0", "description": "Test app"}' }
|
||||
return [PSCustomObject]@{ Rows = @($mockRow) }
|
||||
} else {
|
||||
return [PSCustomObject]@{ Rows = @() }
|
||||
}
|
||||
}
|
||||
Mock ConvertFrom-Json { return [PSCustomObject]@{ version = '1.0.0'; description = 'Test app' } }
|
||||
Mock Out-UTF8File {}
|
||||
|
||||
# Test exact match
|
||||
$result = Get-HistoricalManifestFromDB 'testapp' 'main' '1.0.0'
|
||||
$result.version | Should -Be '1.0.0'
|
||||
$result.source | Should -Be 'sqlite_exact_match'
|
||||
$result.path | Should -Match 'testapp\.json'
|
||||
|
||||
# Test no match - should return null (no version listing in DB function)
|
||||
$result = Get-HistoricalManifestFromDB 'testapp' 'main' '1.0'
|
||||
$result | Should -BeNullOrEmpty
|
||||
}
|
||||
It 'should return null when exact version not available' {
|
||||
Mock Get-ScoopDBItem {
|
||||
@@ -191,34 +168,21 @@ Describe 'Get-HistoricalManifestFromDB' -Tag 'Scoop' {
|
||||
$result | Should -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
Describe 'Get-HistoricalManifest' -Tag 'Scoop' {
|
||||
Describe 'Get-HistoricalManifestFromGitHistory' -Tag 'Scoop' {
|
||||
BeforeAll {
|
||||
Mock Get-HistoricalManifestFromDB { return $null }
|
||||
Mock get_config {
|
||||
param($key, $default)
|
||||
if ($key -eq 'USE_GIT_HISTORY') { return $default }
|
||||
return $false
|
||||
}
|
||||
}
|
||||
It 'should return database result when available' {
|
||||
Mock Get-HistoricalManifestFromDB {
|
||||
return @{
|
||||
path = "C:\temp\testapp.json"
|
||||
version = "1.0.0"
|
||||
source = "sqlite_exact_match"
|
||||
}
|
||||
}
|
||||
$result = Get-HistoricalManifest 'testapp' 'main' '1.0.0'
|
||||
$result.source | Should -Be 'sqlite_exact_match'
|
||||
$result.version | Should -Be '1.0.0'
|
||||
}
|
||||
It 'should return null when no bucket provided' {
|
||||
$result = Get-HistoricalManifest 'testapp' $null '1.0.0'
|
||||
$result = Get-HistoricalManifestFromGitHistory 'testapp' $null '1.0.0'
|
||||
$result | Should -BeNullOrEmpty
|
||||
}
|
||||
It 'should return null when git history disabled' {
|
||||
Mock get_config { return $false }
|
||||
$result = Get-HistoricalManifest 'testapp' 'main' '1.0.0'
|
||||
$result = Get-HistoricalManifestFromGitHistory 'testapp' 'main' '1.0.0'
|
||||
$result | Should -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
@@ -229,7 +193,8 @@ Describe 'generate_user_manifest Enhanced Functionality' -Tag 'Scoop' {
|
||||
Mock warn {}
|
||||
Mock info {}
|
||||
Mock abort { throw "aborted" }
|
||||
Mock Get-HistoricalManifest { return $null }
|
||||
Mock Get-HistoricalManifestFromDB { return $null }
|
||||
Mock Get-HistoricalManifestFromGitHistory { return $null }
|
||||
Mock ensure { return "C:\temp" }
|
||||
Mock usermanifestsdir { return "C:\temp\manifests" }
|
||||
Mock Invoke-AutoUpdate { return "C:\temp\manifests\testapp.json" }
|
||||
@@ -239,12 +204,12 @@ Describe 'generate_user_manifest Enhanced Functionality' -Tag 'Scoop' {
|
||||
$result = generate_user_manifest 'testapp' 'main' '1.5.0'
|
||||
$result | Should -Be "C:\test\manifest.json"
|
||||
}
|
||||
It 'should attempt historical manifest search when versions do not match' {
|
||||
Mock Get-HistoricalManifest {
|
||||
It 'should attempt SQLite cache search first when enabled' {
|
||||
Mock Get-HistoricalManifestFromDB {
|
||||
return @{
|
||||
path = "C:\temp\manifests\testapp.json"
|
||||
version = "1.0.0"
|
||||
source = "git_exact_match:abc123"
|
||||
source = "sqlite_exact_match"
|
||||
}
|
||||
}
|
||||
Mock get_config {
|
||||
@@ -259,8 +224,23 @@ Describe 'generate_user_manifest Enhanced Functionality' -Tag 'Scoop' {
|
||||
$args[0] -like "*Searching for version*in cache*"
|
||||
}
|
||||
}
|
||||
It 'should fallback to git history when cache disabled' {
|
||||
Mock Get-HistoricalManifestFromGitHistory {
|
||||
return @{
|
||||
path = "C:\temp\manifests\testapp.json"
|
||||
version = "1.0.0"
|
||||
source = "git_exact_match:abc123"
|
||||
}
|
||||
}
|
||||
Mock get_config { return $false } # USE_SQLITE_CACHE disabled
|
||||
Mock warn {}
|
||||
$result = generate_user_manifest 'testapp' 'main' '1.0.0'
|
||||
$result | Should -Be "C:\temp\manifests\testapp.json"
|
||||
Should -Invoke -CommandName info -Times 1 -ParameterFilter {
|
||||
$args[0] -like "*Searching for version*in git history*"
|
||||
}
|
||||
}
|
||||
It 'should fallback to autoupdate when historical manifest not found' {
|
||||
Mock Get-HistoricalManifest { return $null }
|
||||
Mock Invoke-AutoUpdate { return "C:\temp\manifests\testapp.json" }
|
||||
Mock Get-Manifest { return @('testapp', @{ version = '2.0.0'; autoupdate = @{} }, 'main', $null) }
|
||||
Mock get_config { return $false } # USE_SQLITE_CACHE disabled
|
||||
@@ -270,4 +250,219 @@ Describe 'generate_user_manifest Enhanced Functionality' -Tag 'Scoop' {
|
||||
$args[0] -like "*No historical version found*"
|
||||
}
|
||||
}
|
||||
It 'should provide helpful guidance when historical manifest not found and no autoupdate' {
|
||||
Mock Get-Manifest { return @('testapp', @{ version = '2.0.0' }, 'main', $null) } # No autoupdate
|
||||
Mock get_config { return $false }
|
||||
Mock Write-Host {}
|
||||
|
||||
{ generate_user_manifest 'testapp' 'main' '1.0.0' } | Should -Throw -ExpectedMessage "*Could not find manifest for 'testapp@1.0.0' and no autoupdate available*"
|
||||
|
||||
Should -Invoke -CommandName info -Times 1 -ParameterFilter {
|
||||
$args[0] -like "*Current version available: 2.0.0*"
|
||||
}
|
||||
Should -Invoke -CommandName Write-Host -Times 1 -ParameterFilter {
|
||||
$args[0] -like "*Install current version: scoop install testapp*"
|
||||
}
|
||||
}
|
||||
It 'should provide enhanced error messages when autoupdate fails' {
|
||||
Mock Get-Manifest { return @('testapp', @{ version = '2.0.0'; autoupdate = @{} }, 'main', $null) }
|
||||
Mock get_config { return $false }
|
||||
Mock Get-ScoopDBItem { return [PSCustomObject]@{ manifest = $null; Rows = @() } }
|
||||
Mock Invoke-AutoUpdate { throw "Autoupdate failed" }
|
||||
Mock Write-Host {}
|
||||
|
||||
{ generate_user_manifest 'testapp' 'main' '1.0.0' } | Should -Throw -ExpectedMessage "*Installation of 'testapp@1.0.0' is not possible*"
|
||||
|
||||
Should -Invoke -CommandName Write-Host -Times 1 -ParameterFilter {
|
||||
$args[0] -like "*Autoupdate failed for version 1.0.0*"
|
||||
}
|
||||
Should -Invoke -CommandName Write-Host -Times 1 -ParameterFilter {
|
||||
$args[0] -like "*Possible reasons:*"
|
||||
}
|
||||
Should -Invoke -CommandName Write-Host -Times 1 -ParameterFilter {
|
||||
$args[0] -like "*Try a different version that was shown in the available list*"
|
||||
}
|
||||
}
|
||||
It 'should indicate autoupdate capability when historical version not found' {
|
||||
Mock Get-Manifest { return @('testapp', @{ version = '2.0.0'; autoupdate = @{} }, 'main', $null) }
|
||||
Mock get_config { return $false }
|
||||
Mock Get-ScoopDBItem { return [PSCustomObject]@{ manifest = $null; Rows = @() } }
|
||||
Mock Invoke-AutoUpdate { return "C:\temp\manifests\testapp.json" }
|
||||
|
||||
$result = generate_user_manifest 'testapp' 'main' '1.0.0'
|
||||
|
||||
Should -Invoke -CommandName info -Times 1 -ParameterFilter {
|
||||
$args[0] -like "*This app supports autoupdate - attempting to generate manifest for version 1.0.0*"
|
||||
}
|
||||
}
|
||||
}
|
||||
Describe 'Exact Match Only Version Handling' -Tag 'Scoop' {
|
||||
BeforeAll {
|
||||
Mock get_config {
|
||||
param($key)
|
||||
if ($key -eq 'USE_SQLITE_CACHE') { return $true }
|
||||
return $false
|
||||
}
|
||||
Mock Get-Command { return $true }
|
||||
Mock ensure { return "C:\temp\manifests" }
|
||||
Mock usermanifestsdir { return "C:\temp\manifests" }
|
||||
Mock Out-UTF8File {}
|
||||
Mock info {}
|
||||
Mock warn {}
|
||||
Mock Write-Host {}
|
||||
}
|
||||
|
||||
It 'should only match exact versions and reject partial matches' {
|
||||
# Mock database with multiple versions available
|
||||
Mock Get-ScoopDBItem {
|
||||
param($Name, $Bucket, $Version)
|
||||
$availableVersions = @('1.0.0', '1.0.1', '1.1.0', '2.0.0')
|
||||
|
||||
if ($Version -in $availableVersions) {
|
||||
$mockRow = [PSCustomObject]@{
|
||||
manifest = '{"version": "' + $Version + '", "description": "Test app"}'
|
||||
version = $Version
|
||||
}
|
||||
return [PSCustomObject]@{ Rows = @($mockRow) }
|
||||
} else {
|
||||
# For non-exact matches, return empty but also simulate showing available versions
|
||||
return [PSCustomObject]@{ Rows = @() }
|
||||
}
|
||||
}
|
||||
Mock ConvertFrom-Json {
|
||||
param($InputObject)
|
||||
$versionMatch = $InputObject | Select-String '"version":\s*"([^"]+)"'
|
||||
if ($versionMatch) {
|
||||
return [PSCustomObject]@{
|
||||
version = $versionMatch.Matches[0].Groups[1].Value
|
||||
description = 'Test app'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Test exact match succeeds
|
||||
$result = Get-HistoricalManifestFromDB 'testapp' 'main' '1.0.0'
|
||||
$result.version | Should -Be '1.0.0'
|
||||
$result.source | Should -Be 'sqlite_exact_match'
|
||||
|
||||
# Test partial match fails (should not match 1.0.0 when looking for '1.0')
|
||||
$result = Get-HistoricalManifestFromDB 'testapp' 'main' '1.0'
|
||||
$result | Should -BeNullOrEmpty
|
||||
|
||||
# Test prefix match fails (should not match 1.0.0 when looking for '1')
|
||||
$result = Get-HistoricalManifestFromDB 'testapp' 'main' '1'
|
||||
$result | Should -BeNullOrEmpty
|
||||
|
||||
# Test non-existent version fails
|
||||
$result = Get-HistoricalManifestFromDB 'testapp' 'main' '3.0.0'
|
||||
$result | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'should display available versions when exact match not found' {
|
||||
# Mock database to simulate showing available versions when exact match fails
|
||||
Mock Get-ScoopDBItem {
|
||||
param($Name, $Bucket, $Version)
|
||||
$availableVersions = @('1.0.0', '1.0.1', '1.1.0', '2.0.0')
|
||||
|
||||
if ($Version -eq '1.5.0') {
|
||||
# Simulate that when we query for non-existent version,
|
||||
# the database function would show available versions
|
||||
Mock info {
|
||||
param($message)
|
||||
if ($message -like "*Available versions*") {
|
||||
# This simulates the behavior we expect
|
||||
}
|
||||
} -Verifiable
|
||||
return [PSCustomObject]@{ Rows = @() }
|
||||
} elseif ($Version -in $availableVersions) {
|
||||
$mockRow = [PSCustomObject]@{
|
||||
manifest = '{"version": "' + $Version + '", "description": "Test app"}'
|
||||
version = $Version
|
||||
}
|
||||
return [PSCustomObject]@{ Rows = @($mockRow) }
|
||||
} else {
|
||||
return [PSCustomObject]@{ Rows = @() }
|
||||
}
|
||||
}
|
||||
|
||||
# Test that when no exact match is found, available versions should be shown
|
||||
$result = Get-HistoricalManifestFromDB 'testapp' 'main' '1.5.0'
|
||||
$result | Should -BeNullOrEmpty
|
||||
|
||||
# The actual implementation should call info to show available versions
|
||||
# This test verifies that the behavior exists
|
||||
}
|
||||
|
||||
It 'should reject fuzzy or best match attempts' {
|
||||
Mock Get-ScoopDBItem {
|
||||
param($Name, $Bucket, $Version)
|
||||
# Simulate database with versions that could be "close matches"
|
||||
$availableVersions = @('1.0.0', '1.0.1', '1.0.2')
|
||||
|
||||
# Only return results for exact matches
|
||||
if ($Version -in $availableVersions) {
|
||||
$mockRow = [PSCustomObject]@{
|
||||
manifest = '{"version": "' + $Version + '", "description": "Test app"}'
|
||||
version = $Version
|
||||
}
|
||||
return [PSCustomObject]@{ Rows = @($mockRow) }
|
||||
}
|
||||
return [PSCustomObject]@{ Rows = @() }
|
||||
}
|
||||
|
||||
# These should all fail because they're not exact matches
|
||||
$testCases = @(
|
||||
@{ version = '1.0'; description = 'partial version' },
|
||||
@{ version = '1.0.*'; description = 'wildcard version' },
|
||||
@{ version = '~1.0.0'; description = 'tilde range' },
|
||||
@{ version = '^1.0.0'; description = 'caret range' },
|
||||
@{ version = 'latest'; description = 'latest keyword' },
|
||||
@{ version = '1.0.0-beta'; description = 'prerelease when stable exists' }
|
||||
)
|
||||
|
||||
foreach ($testCase in $testCases) {
|
||||
$result = Get-HistoricalManifestFromDB 'testapp' 'main' $testCase.version
|
||||
$result | Should -BeNullOrEmpty -Because "$($testCase.description) should not match any version"
|
||||
}
|
||||
}
|
||||
|
||||
It 'should handle version comparison edge cases correctly' {
|
||||
Mock Get-ScoopDBItem {
|
||||
param($Name, $Bucket, $Version)
|
||||
$availableVersions = @('1.0.0', '1.0.0-alpha', '1.0.0-beta', '1.0.0+build.1')
|
||||
|
||||
if ($Version -in $availableVersions) {
|
||||
$mockRow = [PSCustomObject]@{
|
||||
manifest = '{"version": "' + $Version + '", "description": "Test app"}'
|
||||
version = $Version
|
||||
}
|
||||
return [PSCustomObject]@{ Rows = @($mockRow) }
|
||||
}
|
||||
return [PSCustomObject]@{ Rows = @() }
|
||||
}
|
||||
Mock ConvertFrom-Json {
|
||||
param($InputObject)
|
||||
$versionMatch = $InputObject | Select-String '"version":\s*"([^"]+)"'
|
||||
if ($versionMatch) {
|
||||
return [PSCustomObject]@{
|
||||
version = $versionMatch.Matches[0].Groups[1].Value
|
||||
description = 'Test app'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Exact matches should work
|
||||
$result = Get-HistoricalManifestFromDB 'testapp' 'main' '1.0.0'
|
||||
$result.version | Should -Be '1.0.0'
|
||||
|
||||
$result = Get-HistoricalManifestFromDB 'testapp' 'main' '1.0.0-alpha'
|
||||
$result.version | Should -Be '1.0.0-alpha'
|
||||
|
||||
$result = Get-HistoricalManifestFromDB 'testapp' 'main' '1.0.0+build.1'
|
||||
$result.version | Should -Be '1.0.0+build.1'
|
||||
|
||||
# Non-exact matches should fail
|
||||
$result = Get-HistoricalManifestFromDB 'testapp' 'main' '1.0.0-gamma' # Not available
|
||||
$result | Should -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user