From 6ee8c09ba04279018d471b99478983f4032e8893 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Tue, 25 Oct 2022 00:42:27 +0800 Subject: [PATCH] Fix tests for Pester 5 --- PSScriptAnalyzerSettings.psd1 | 3 - test/00-Project.Tests.ps1 | 74 ------------- test/Import-Bucket-Tests.ps1 | 158 ++++++++------------------ test/Import-File-Tests.ps1 | 134 ---------------------- test/Scoop-00File.Tests.ps1 | 189 ++++++++++++++++++++++++++++++++ test/Scoop-00Linting.Tests.ps1 | 32 ++++++ test/Scoop-Alias.Tests.ps1 | 10 +- test/Scoop-Config.Tests.ps1 | 6 +- test/Scoop-Core.Tests.ps1 | 67 ++++++----- test/Scoop-Decompress.Tests.ps1 | 14 ++- test/Scoop-Depends.Tests.ps1 | 14 ++- test/Scoop-GetOpts.Tests.ps1 | 6 +- test/Scoop-Install.Tests.ps1 | 28 +++-- test/Scoop-Linting.Tests.ps1 | 41 ------- test/Scoop-Manifest.Tests.ps1 | 71 +++++++++--- test/Scoop-Versions.Tests.ps1 | 6 +- 16 files changed, 403 insertions(+), 450 deletions(-) delete mode 100644 test/00-Project.Tests.ps1 delete mode 100644 test/Import-File-Tests.ps1 create mode 100644 test/Scoop-00File.Tests.ps1 create mode 100644 test/Scoop-00Linting.Tests.ps1 delete mode 100644 test/Scoop-Linting.Tests.ps1 diff --git a/PSScriptAnalyzerSettings.psd1 b/PSScriptAnalyzerSettings.psd1 index 8b76f02a71..9ef165869e 100644 --- a/PSScriptAnalyzerSettings.psd1 +++ b/PSScriptAnalyzerSettings.psd1 @@ -1,6 +1,3 @@ -# The PowerShell Script Analyzer will generate a warning -# diagnostic record for this file due to a bug - -# https://github.com/PowerShell/PSScriptAnalyzer/issues/472 @{ # Only diagnostic records of the specified severity will be generated. # Uncomment the following line if you only want Errors and Warnings but diff --git a/test/00-Project.Tests.ps1 b/test/00-Project.Tests.ps1 deleted file mode 100644 index c45d45c708..0000000000 --- a/test/00-Project.Tests.ps1 +++ /dev/null @@ -1,74 +0,0 @@ -$repo_dir = (Get-Item $MyInvocation.MyCommand.Path).Directory.Parent.FullName - -$repo_files = @( Get-ChildItem $repo_dir -File -Recurse -Force ) - -$project_file_exclusions = @( - '[\\/]\.git[\\/]', - '\.sublime-workspace$', - '\.DS_Store$', - 'supporting(\\|/)validator(\\|/)packages(\\|/)*', - 'supporting(\\|/)shimexe(\\|/)packages(\\|/)*' -) - -Describe 'Project code' { - - $files = @( - $repo_files | - Where-Object { $_.fullname -inotmatch $($project_file_exclusions -join '|') } | - Where-Object { $_.fullname -imatch '.(ps1|psm1)$' } - ) - - $files_exist = ($files.Count -gt 0) - - It $('PowerShell code files exist ({0} found)' -f $files.Count) -Skip:$(-not $files_exist) { - if (-not ($files.Count -gt 0)) { - throw 'No PowerShell code files were found' - } - } - - function Test-PowerShellSyntax { - # ref: http://powershell.org/wp/forums/topic/how-to-check-syntax-of-scripts-automatically @@ https://archive.is/xtSv6 - # originally created by Alexander Petrovskiy & Dave Wyatt - [CmdletBinding()] - param ( - [Parameter(Mandatory = $true, ValueFromPipeline = $true)] - [string[]] - $Path - ) - - process { - foreach ($scriptPath in $Path) { - $contents = Get-Content -Path $scriptPath - - if ($null -eq $contents) { - continue - } - - $errors = $null - $null = [System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors) - - New-Object psobject -Property @{ - Path = $scriptPath - SyntaxErrorsFound = ($errors.Count -gt 0) - } - } - } - } - - It 'PowerShell code files do not contain syntax errors' -Skip:$(-not $files_exist) { - $badFiles = @( - foreach ($file in $files) { - if ( (Test-PowerShellSyntax $file.FullName).SyntaxErrorsFound ) { - $file.FullName - } - } - ) - - if ($badFiles.Count -gt 0) { - throw "The following files have syntax errors: `r`n`r`n$($badFiles -join "`r`n")" - } - } - -} - -. "$PSScriptRoot\Import-File-Tests.ps1" diff --git a/test/Import-Bucket-Tests.ps1 b/test/Import-Bucket-Tests.ps1 index b42b3bdc7f..93cc9e404f 100644 --- a/test/Import-Bucket-Tests.ps1 +++ b/test/Import-Bucket-Tests.ps1 @@ -1,127 +1,63 @@ -#Requires -Version 5.0 -#Requires -Modules @{ ModuleName = 'Pester'; RequiredVersion = '4.10.1' } +#Requires -Version 5.1 +#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.2.0' } param( - [ValidateNotNullOrEmpty()] - [String] - $repo_dir = (Split-Path -Path $MyInvocation.PSCommandPath -Parent) + [String] $BucketPath = $MyInvocation.PSScriptRoot ) -. "$PSScriptRoot\Scoop-TestLib.ps1" -. "$PSScriptRoot\..\lib\manifest.ps1" -. "$PSScriptRoot\..\lib\unix.ps1" +. "$PSScriptRoot\Scoop-00File.Tests.ps1" -TestPath $BucketPath -$bucketdir = $repo_dir -if (Test-Path("$repo_dir\..\bucket")) { - $bucketdir = "$repo_dir\..\bucket" -} elseif (Test-Path("$repo_dir\bucket")) { - $bucketdir = "$repo_dir\bucket" -} - -# Tests for non manifest files -$repo_files = @(Get-ChildItem -Path $repo_dir -File -Recurse) -$project_file_exclusions = @( - '[\\/]\.git[\\/]', - '.sublime-workspace$', - '.DS_Store$' -) -. "$PSScriptRoot\Import-File-Tests.ps1" - -# Tests for manifest files -Describe 'Manifest Validator' -Tag 'Validator' { - BeforeAll { - $schema = "$PSScriptRoot\..\schema.json" - $working_dir = setup_working 'manifest' - Add-Type -Path "$PSScriptRoot\..\supporting\validator\bin\Newtonsoft.Json.dll" - Add-Type -Path "$PSScriptRoot\..\supporting\validator\bin\Newtonsoft.Json.Schema.dll" - Add-Type -Path "$PSScriptRoot\..\supporting\validator\bin\Scoop.Validator.dll" - } - - It 'Scoop.Validator is available' { - ([System.Management.Automation.PSTypeName]'Scoop.Validator').Type | Should -Be 'Scoop.Validator' - } - - Context 'parse_json function' { - It 'fails with invalid json' { - { parse_json "$working_dir\broken_wget.json" } | Should -Throw +Describe 'Manifest validates against the schema' { + BeforeDiscovery { + $bucketDir = if (Test-Path "$BucketPath\bucket") { + "$BucketPath\bucket" + } else { + $BucketPath } - } - - Context 'schema validation' { - It 'fails with broken schema' { - $validator = New-Object Scoop.Validator("$working_dir\broken_schema.json", $true) - $validator.Validate("$working_dir\wget.json") | Should -BeFalse - $validator.Errors.Count | Should -Be 1 - $validator.Errors | Select-Object -First 1 | Should -Match 'broken_schema.*(line 6).*(position 4)' - } - It 'fails with broken manifest' { - $validator = New-Object Scoop.Validator($schema, $true) - $validator.Validate("$working_dir\broken_wget.json") | Should -BeFalse - $validator.Errors.Count | Should -Be 1 - $validator.Errors | Select-Object -First 1 | Should -Match 'broken_wget.*(line 5).*(position 4)' + if ($env:CI -eq $true) { + $commit = if ($env:GITHUB_SHA) { + # GitHub Actions + $env:GITHUB_SHA + } elseif ($env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) { + # AppVeyor + $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT + } else { + $env:APPVEYOR_REPO_COMMIT + } + if ($commit) { + $changedManifests = @(Get-GitChangedFile -Path $bucketDir -Include '*.json' -Commit $commit) + } } - It 'fails with invalid manifest' { - $validator = New-Object Scoop.Validator($schema, $true) - $validator.Validate("$working_dir\invalid_wget.json") | Should -BeFalse - $validator.Errors.Count | Should -Be 16 - $validator.Errors | Select-Object -First 1 | Should -Match "Property 'randomproperty' has not been defined and the schema does not allow additional properties\." - $validator.Errors | Select-Object -Last 1 | Should -Match 'Required properties are missing from object: version\.' + $manifestFiles = (Get-ChildItem $bucketDir -Filter '*.json' -Recurse).FullName + if ($changedManifests) { + $manifestFiles = $manifestFiles | Where-Object { $_ -in $changedManifests } } } -} -Describe 'manifest validates against the schema' -Tag 'Manifests' { BeforeAll { - $schema = "$PSScriptRoot\..\schema.json" - $changed_manifests = @() - if ($env:CI -eq $true) { - # AppVeyor - $commit = if ($env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) { $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT } else { $env:APPVEYOR_REPO_COMMIT } - - # GitHub Actions - if ($env:GITHUB_SHA) { - $commit = $env:GITHUB_SHA - } - $changed_manifests = (Get-GitChangedFile -Path $repo_dir -Include '*.json' -Commit $commit) - } - $manifest_files = Get-ChildItem $bucketdir -Filter '*.json' -Recurse - $validator = New-Object Scoop.Validator($schema, $true) + Add-Type -Path "$PSScriptRoot\..\supporting\validator\bin\Scoop.Validator.dll" + # Could not use backslash '\' in Linux/macOS for .NET object 'Scoop.Validator' + $validator = New-Object Scoop.Validator("$PSScriptRoot/../schema.json", $true) + $global:quotaExceeded = $false } - - $quota_exceeded = $false - - $manifest_files | ForEach-Object { - $skip_manifest = ($changed_manifests -inotcontains $_.FullName) - if ($env:CI -ne $true -or $changed_manifests -imatch 'schema.json') { - $skip_manifest = $false - } - It "$_" -Skip:$skip_manifest { + It '<_>' -TestCases $manifestFiles { + if ($global:quotaExceeded) { + Set-ItResult -Skipped -Because 'Schema validation limit exceeded.' + } else { $file = $_ # exception handling may overwrite $_ - - if (!($quota_exceeded)) { - try { - $validator.Validate($file.fullname) - - if ($validator.Errors.Count -gt 0) { - Write-Host -f red " [-] $_ has $($validator.Errors.Count) Error$(If($validator.Errors.Count -gt 1) { 's' })!" - Write-Host -f yellow $validator.ErrorsAsString - } - $validator.Errors.Count | Should -Be 0 - } catch { - if ($_.exception.message -like '*The free-quota limit of 1000 schema validations per hour has been reached.*') { - $quota_exceeded = $true - Write-Host -f darkyellow 'Schema validation limit exceeded. Will skip further validations.' - } else { - throw - } + try { + $validator.Validate($file) + if ($validator.Errors.Count -gt 0) { + Write-Host " [-] $_ has $($validator.Errors.Count) Error$(If($validator.Errors.Count -gt 1) { 's' })!" -ForegroundColor Red + Write-Host $validator.ErrorsAsString -ForegroundColor Yellow + } + $validator.Errors.Count | Should -Be 0 + } catch { + if ($_.Exception.Message -like '*The free-quota limit of 1000 schema validations per hour has been reached.*') { + $global:quotaExceeded = $true + Set-ItResult -Skipped -Because 'Schema validation limit exceeded.' + } else { + throw } } - - $manifest = parse_json $file.fullname - $url = arch_specific 'url' $manifest '32bit' - $url64 = arch_specific 'url' $manifest '64bit' - if (!$url) { - $url = $url64 - } - $url | Should -Not -BeNullOrEmpty } } } diff --git a/test/Import-File-Tests.ps1 b/test/Import-File-Tests.ps1 deleted file mode 100644 index 5aadcd3ade..0000000000 --- a/test/Import-File-Tests.ps1 +++ /dev/null @@ -1,134 +0,0 @@ -if ([String]::IsNullOrEmpty($MyInvocation.PSScriptRoot)) { - Write-Error 'This script should not be called directly! It has to be imported from a buckets test file!' - exit 1 -} - -Describe 'Style constraints for non-binary project files' { - - $files = @( - # gather all files except '*.exe', '*.zip', or any .git repository files - $repo_files | - Where-Object { $_.fullname -inotmatch $($project_file_exclusions -join '|') } | - Where-Object { $_.fullname -inotmatch '(.exe|.zip|.dll)$' } | - Where-Object { $_.fullname -inotmatch '(unformatted)' } - ) - - $files_exist = ($files.Count -gt 0) - - It $('non-binary project files exist ({0} found)' -f $files.Count) -Skip:$(-not $files_exist) { - if (-not ($files.Count -gt 0)) { - throw 'No non-binary project were found' - } - } - - It 'files do not contain leading UTF-8 BOM' -Skip:$(-not $files_exist) { - # UTF-8 BOM == 0xEF 0xBB 0xBF - # see http://www.powershellmagazine.com/2012/12/17/pscxtip-how-to-determine-the-byte-order-mark-of-a-text-file @@ https://archive.is/RgT42 - # ref: http://poshcode.org/2153 @@ https://archive.is/sGnnu - $badFiles = @( - foreach ($file in $files) { - if ((Get-Command Get-Content).parameters.ContainsKey('AsByteStream')) { - # PowerShell Core (6.0+) '-Encoding byte' is replaced by '-AsByteStream' - $content = ([char[]](Get-Content $file.FullName -AsByteStream -TotalCount 3) -join '') - } else { - $content = ([char[]](Get-Content $file.FullName -Encoding byte -TotalCount 3) -join '') - } - if ([regex]::match($content, '(?ms)^\xEF\xBB\xBF').success) { - $file.FullName - } - } - ) - - if ($badFiles.Count -gt 0) { - throw "The following files have utf-8 BOM: `r`n`r`n$($badFiles -join "`r`n")" - } - } - - It 'files end with a newline' -Skip:$(-not $files_exist) { - $badFiles = @( - foreach ($file in $files) { - # Ignore previous TestResults.xml - if ($file -match 'TestResults.xml') { - continue - } - $string = [System.IO.File]::ReadAllText($file.FullName) - if ($string.Length -gt 0 -and $string[-1] -ne "`n") { - $file.FullName - } - } - ) - - if ($badFiles.Count -gt 0) { - throw "The following files do not end with a newline: `r`n`r`n$($badFiles -join "`r`n")" - } - } - - It 'file newlines are CRLF' -Skip:$(-not $files_exist) { - $badFiles = @( - foreach ($file in $files) { - $content = [System.IO.File]::ReadAllText($file.FullName) - if (!$content) { - throw "File contents are null: $($file.FullName)" - } - $lines = [regex]::split($content, '\r\n') - $lineCount = $lines.Count - - for ($i = 0; $i -lt $lineCount; $i++) { - if ( [regex]::match($lines[$i], '\r|\n').success ) { - $file.FullName - break - } - } - } - ) - - if ($badFiles.Count -gt 0) { - throw "The following files have non-CRLF line endings: `r`n`r`n$($badFiles -join "`r`n")" - } - } - - It 'files have no lines containing trailing whitespace' -Skip:$(-not $files_exist) { - $badLines = @( - foreach ($file in $files) { - # Ignore previous TestResults.xml - if ($file -match 'TestResults.xml') { - continue - } - $lines = [System.IO.File]::ReadAllLines($file.FullName) - $lineCount = $lines.Count - - for ($i = 0; $i -lt $lineCount; $i++) { - if ($lines[$i] -match '\s+$') { - 'File: {0}, Line: {1}' -f $file.FullName, ($i + 1) - } - } - } - ) - - if ($badLines.Count -gt 0) { - throw "The following $($badLines.Count) lines contain trailing whitespace: `r`n`r`n$($badLines -join "`r`n")" - } - } - - It 'any leading whitespace consists only of spaces (excepting makefiles)' -Skip:$(-not $files_exist) { - $badLines = @( - foreach ($file in $files) { - if ($file.fullname -inotmatch '(^|.)makefile$') { - $lines = [System.IO.File]::ReadAllLines($file.FullName) - $lineCount = $lines.Count - - for ($i = 0; $i -lt $lineCount; $i++) { - if ($lines[$i] -notmatch '^[ ]*(\S|$)') { - 'File: {0}, Line: {1}' -f $file.FullName, ($i + 1) - } - } - } - } - ) - - if ($badLines.Count -gt 0) { - throw "The following $($badLines.Count) lines contain TABs within leading whitespace: `r`n`r`n$($badLines -join "`r`n")" - } - } - -} diff --git a/test/Scoop-00File.Tests.ps1 b/test/Scoop-00File.Tests.ps1 new file mode 100644 index 0000000000..4161c37792 --- /dev/null +++ b/test/Scoop-00File.Tests.ps1 @@ -0,0 +1,189 @@ +param( + [String] $TestPath = "$PSScriptRoot\.." +) + +BeforeDiscovery { + $project_file_exclusions = @( + '[\\/]\.git[\\/]', + '\.sublime-workspace$', + '\.DS_Store$', + 'supporting(\\|/)validator(\\|/)packages(\\|/)*', + 'supporting(\\|/)shimexe(\\|/)packages(\\|/)*' + ) + $repo_files = (Get-ChildItem $TestPath -File -Recurse).FullName | + Where-Object { $_ -inotmatch $($project_file_exclusions -join '|') } +} + +Describe 'Code Syntax' -ForEach @(, $repo_files) -Tag 'File' { + BeforeAll { + $files = @( + $_ | Where-Object { $_ -imatch '.(ps1|psm1)$' } + ) + function Test-PowerShellSyntax { + # ref: http://powershell.org/wp/forums/topic/how-to-check-syntax-of-scripts-automatically @@ https://archive.is/xtSv6 + # originally created by Alexander Petrovskiy & Dave Wyatt + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [string[]] + $Path + ) + + process { + foreach ($scriptPath in $Path) { + $contents = Get-Content -Path $scriptPath + + if ($null -eq $contents) { + continue + } + + $errors = $null + $null = [System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors) + + New-Object psobject -Property @{ + Path = $scriptPath + SyntaxErrorsFound = ($errors.Count -gt 0) + } + } + } + } + + } + + It 'PowerShell code files do not contain syntax errors' { + $badFiles = @( + foreach ($file in $files) { + if ( (Test-PowerShellSyntax $file).SyntaxErrorsFound ) { + $file + } + } + ) + + if ($badFiles.Count -gt 0) { + throw "The following files have syntax errors: `r`n`r`n$($badFiles -join "`r`n")" + } + } + +} + +Describe 'Style constraints for non-binary project files' -ForEach @(, $repo_files) -Tag 'File' { + BeforeAll { + $files = @( + # gather all files except '*.exe', '*.zip', or any .git repository files + $_ | + Where-Object { $_ -inotmatch '(.exe|.zip|.dll)$' } | + Where-Object { $_ -inotmatch '(unformatted)' } + ) + } + + It 'files do not contain leading UTF-8 BOM' { + # UTF-8 BOM == 0xEF 0xBB 0xBF + # see http://www.powershellmagazine.com/2012/12/17/pscxtip-how-to-determine-the-byte-order-mark-of-a-text-file @@ https://archive.is/RgT42 + # ref: http://poshcode.org/2153 @@ https://archive.is/sGnnu + $badFiles = @( + foreach ($file in $files) { + if ((Get-Command Get-Content).parameters.ContainsKey('AsByteStream')) { + # PowerShell Core (6.0+) '-Encoding byte' is replaced by '-AsByteStream' + $content = ([char[]](Get-Content $file -AsByteStream -TotalCount 3) -join '') + } else { + $content = ([char[]](Get-Content $file -Encoding byte -TotalCount 3) -join '') + } + if ([regex]::match($content, '(?ms)^\xEF\xBB\xBF').success) { + $file + } + } + ) + + if ($badFiles.Count -gt 0) { + throw "The following files have utf-8 BOM: `r`n`r`n$($badFiles -join "`r`n")" + } + } + + It 'files end with a newline' { + $badFiles = @( + foreach ($file in $files) { + # Ignore previous TestResults.xml + if ($file -match 'TestResults.xml') { + continue + } + $string = [System.IO.File]::ReadAllText($file) + if ($string.Length -gt 0 -and $string[-1] -ne "`n") { + $file + } + } + ) + + if ($badFiles.Count -gt 0) { + throw "The following files do not end with a newline: `r`n`r`n$($badFiles -join "`r`n")" + } + } + + It 'file newlines are CRLF' { + $badFiles = @( + foreach ($file in $files) { + $content = [System.IO.File]::ReadAllText($file) + if (!$content) { + throw "File contents are null: $($file)" + } + $lines = [regex]::split($content, '\r\n') + $lineCount = $lines.Count + + for ($i = 0; $i -lt $lineCount; $i++) { + if ( [regex]::match($lines[$i], '\r|\n').success ) { + $file + break + } + } + } + ) + + if ($badFiles.Count -gt 0) { + throw "The following files have non-CRLF line endings: `r`n`r`n$($badFiles -join "`r`n")" + } + } + + It 'files have no lines containing trailing whitespace' { + $badLines = @( + foreach ($file in $files) { + # Ignore previous TestResults.xml + if ($file -match 'TestResults.xml') { + continue + } + $lines = [System.IO.File]::ReadAllLines($file) + $lineCount = $lines.Count + + for ($i = 0; $i -lt $lineCount; $i++) { + if ($lines[$i] -match '\s+$') { + 'File: {0}, Line: {1}' -f $file, ($i + 1) + } + } + } + ) + + if ($badLines.Count -gt 0) { + throw "The following $($badLines.Count) lines contain trailing whitespace: `r`n`r`n$($badLines -join "`r`n")" + } + } + + It 'any leading whitespace consists only of spaces (excepting makefiles)' { + $badLines = @( + foreach ($file in $files) { + if ($file -inotmatch '(^|.)makefile$') { + $lines = [System.IO.File]::ReadAllLines($file) + $lineCount = $lines.Count + + for ($i = 0; $i -lt $lineCount; $i++) { + if ($lines[$i] -notmatch '^[ ]*(\S|$)') { + 'File: {0}, Line: {1}' -f $file, ($i + 1) + } + } + } + } + ) + + if ($badLines.Count -gt 0) { + throw "The following $($badLines.Count) lines contain TABs within leading whitespace: `r`n`r`n$($badLines -join "`r`n")" + } + } + +} diff --git a/test/Scoop-00Linting.Tests.ps1 b/test/Scoop-00Linting.Tests.ps1 new file mode 100644 index 0000000000..7d722fa3b0 --- /dev/null +++ b/test/Scoop-00Linting.Tests.ps1 @@ -0,0 +1,32 @@ +BeforeDiscovery { + $scriptDir = @('bin', 'lib', 'libexec', 'test') +} + +Describe 'PSScriptAnalyzer' -Tag 'Linter' { + BeforeAll { + $lintSettings = "$PSScriptRoot\..\PSScriptAnalyzerSettings.psd1" + } + + It 'PSScriptAnalyzerSettings.ps1 should exist' { + $lintSettings | Should -Exist + } + Context 'Linting all *.psd1, *.psm1 and *.ps1 files' { + BeforeEach { + $analysis = Invoke-ScriptAnalyzer -Path "$PSScriptRoot\..\$_" -Settings $lintSettings + } + It 'Should pass: <_>' -TestCases $scriptDir { + $analysis | Should -HaveCount 0 + if ($analysis) { + foreach ($result in $analysis) { + switch -wildCard ($result.ScriptName) { + '*.psm1' { $type = 'Module' } + '*.ps1' { $type = 'Script' } + '*.psd1' { $type = 'Manifest' } + } + Write-Host -f Yellow " [*] $($result.Severity): $($result.Message)" + Write-Host -f Yellow " $($result.RuleName) in $type`: $directory\$($result.ScriptName):$($result.Line)" + } + } + } + } +} diff --git a/test/Scoop-Alias.Tests.ps1 b/test/Scoop-Alias.Tests.ps1 index 957b2d91b1..bd365718a8 100644 --- a/test/Scoop-Alias.Tests.ps1 +++ b/test/Scoop-Alias.Tests.ps1 @@ -1,7 +1,9 @@ -. "$PSScriptRoot\Scoop-TestLib.ps1" -. "$PSScriptRoot\..\lib\core.ps1" -. "$PSScriptRoot\..\lib\help.ps1" -. "$PSScriptRoot\..\libexec\scoop-alias.ps1" | Out-Null +BeforeAll { + . "$PSScriptRoot\Scoop-TestLib.ps1" + . "$PSScriptRoot\..\lib\core.ps1" + . "$PSScriptRoot\..\lib\help.ps1" + . "$PSScriptRoot\..\libexec\scoop-alias.ps1" | Out-Null +} Describe 'Manipulate Alias' -Tag 'Scoop' { BeforeAll { diff --git a/test/Scoop-Config.Tests.ps1 b/test/Scoop-Config.Tests.ps1 index 4b2e81ff6e..9826af82a2 100644 --- a/test/Scoop-Config.Tests.ps1 +++ b/test/Scoop-Config.Tests.ps1 @@ -1,5 +1,7 @@ -. "$PSScriptRoot\Scoop-TestLib.ps1" -. "$PSScriptRoot\..\lib\core.ps1" +BeforeAll { + . "$PSScriptRoot\Scoop-TestLib.ps1" + . "$PSScriptRoot\..\lib\core.ps1" +} Describe 'config' -Tag 'Scoop' { BeforeAll { diff --git a/test/Scoop-Core.Tests.ps1 b/test/Scoop-Core.Tests.ps1 index bdcd29c1ac..4c95067e23 100644 --- a/test/Scoop-Core.Tests.ps1 +++ b/test/Scoop-Core.Tests.ps1 @@ -1,8 +1,8 @@ -. "$PSScriptRoot\Scoop-TestLib.ps1" -. "$PSScriptRoot\..\lib\core.ps1" -. "$PSScriptRoot\..\lib\install.ps1" - -$repo_dir = (Get-Item $MyInvocation.MyCommand.Path).directory.parent.FullName +BeforeAll { + . "$PSScriptRoot\Scoop-TestLib.ps1" + . "$PSScriptRoot\..\lib\core.ps1" + . "$PSScriptRoot\..\lib\install.ps1" +} Describe 'Get-AppFilePath' -Tag 'Scoop' { BeforeAll { @@ -127,11 +127,10 @@ Describe 'is_directory' -Tag 'Scoop' { } Describe 'movedir' -Tag 'Scoop', 'Windows' { - $extract_dir = 'subdir' - $extract_to = $null - BeforeAll { $working_dir = setup_working 'movedir' + $extract_dir = 'subdir' + $extract_to = $null } It 'moves directories with no spaces in path' { @@ -184,15 +183,13 @@ Describe 'shim' -Tag 'Scoop', 'Windows' { shim-test | Should -Be 'Hello, world!' } - Context 'user with quote' { - It 'shims a file with quote in path' { - { Get-Command 'shim-test' -ea stop } | Should -Throw - { shim-test } | Should -Throw + It 'shims a file with quote in path' { + { Get-Command 'shim-test' -ea stop } | Should -Throw + { shim-test } | Should -Throw - shim "$working_dir\user with 'quote\shim-test.ps1" $false 'shim-test' - { Get-Command 'shim-test' -ea stop } | Should -Not -Throw - shim-test | Should -Be 'Hello, world!' - } + shim "$working_dir\user with 'quote\shim-test.ps1" $false 'shim-test' + { Get-Command 'shim-test' -ea stop } | Should -Not -Throw + shim-test | Should -Be 'Hello, world!' } AfterEach { @@ -262,34 +259,32 @@ Describe 'get_app_name_from_shim' -Tag 'Scoop', 'Windows' { } Describe 'ensure_robocopy_in_path' -Tag 'Scoop', 'Windows' { - $shimdir = shimdir $false - Mock versiondir { $repo_dir } + BeforeAll { + $shimdir = shimdir $false + Mock versiondir { "$PSScriptRoot\.." } + } - Context 'robocopy is not in path' { - It 'shims robocopy when not on path' { - Mock Test-CommandAvailable { $false } - Test-CommandAvailable robocopy | Should -Be $false + It 'shims robocopy when not on path' { + Mock Test-CommandAvailable { $false } + Test-CommandAvailable robocopy | Should -Be $false - ensure_robocopy_in_path + ensure_robocopy_in_path - # "$shimdir/robocopy.ps1" | should -exist - "$shimdir/robocopy.exe" | Should -Exist + # "$shimdir/robocopy.ps1" | should -exist + "$shimdir/robocopy.exe" | Should -Exist - # clean up - rm_shim robocopy $(shimdir $false) | Out-Null - } + # clean up + rm_shim robocopy $(shimdir $false) | Out-Null } - Context 'robocopy is in path' { - It 'does not shim robocopy when it is in path' { - Mock Test-CommandAvailable { $true } - Test-CommandAvailable robocopy | Should -Be $true + It 'does not shim robocopy when it is in path' { + Mock Test-CommandAvailable { $true } + Test-CommandAvailable robocopy | Should -Be $true - ensure_robocopy_in_path + ensure_robocopy_in_path - # "$shimdir/robocopy.ps1" | should -not -exist - "$shimdir/robocopy.exe" | Should -Not -Exist - } + # "$shimdir/robocopy.ps1" | should -not -exist + "$shimdir/robocopy.exe" | Should -Not -Exist } } diff --git a/test/Scoop-Decompress.Tests.ps1 b/test/Scoop-Decompress.Tests.ps1 index 81e42ffad2..b4cc1ef2d1 100644 --- a/test/Scoop-Decompress.Tests.ps1 +++ b/test/Scoop-Decompress.Tests.ps1 @@ -1,9 +1,11 @@ -. "$PSScriptRoot\Scoop-TestLib.ps1" -. "$PSScriptRoot\..\lib\core.ps1" -. "$PSScriptRoot\..\lib\decompress.ps1" -. "$PSScriptRoot\..\lib\install.ps1" -. "$PSScriptRoot\..\lib\manifest.ps1" -. "$PSScriptRoot\..\lib\versions.ps1" +BeforeAll { + . "$PSScriptRoot\Scoop-TestLib.ps1" + . "$PSScriptRoot\..\lib\core.ps1" + . "$PSScriptRoot\..\lib\decompress.ps1" + . "$PSScriptRoot\..\lib\install.ps1" + . "$PSScriptRoot\..\lib\manifest.ps1" + . "$PSScriptRoot\..\lib\versions.ps1" +} Describe 'Decompression function' -Tag 'Scoop', 'Windows', 'Decompress' { diff --git a/test/Scoop-Depends.Tests.ps1 b/test/Scoop-Depends.Tests.ps1 index b465d28220..d80d7d2652 100644 --- a/test/Scoop-Depends.Tests.ps1 +++ b/test/Scoop-Depends.Tests.ps1 @@ -1,9 +1,11 @@ -. "$PSScriptRoot\Scoop-TestLib.ps1" -. "$PSScriptRoot\..\lib\core.ps1" -. "$PSScriptRoot\..\lib\depends.ps1" -. "$PSScriptRoot\..\lib\buckets.ps1" -. "$PSScriptRoot\..\lib\install.ps1" -. "$PSScriptRoot\..\lib\manifest.ps1" +BeforeAll { + . "$PSScriptRoot\Scoop-TestLib.ps1" + . "$PSScriptRoot\..\lib\core.ps1" + . "$PSScriptRoot\..\lib\depends.ps1" + . "$PSScriptRoot\..\lib\buckets.ps1" + . "$PSScriptRoot\..\lib\install.ps1" + . "$PSScriptRoot\..\lib\manifest.ps1" +} Describe 'Package Dependencies' -Tag 'Scoop' { Context 'Requirement function' { diff --git a/test/Scoop-GetOpts.Tests.ps1 b/test/Scoop-GetOpts.Tests.ps1 index 2fcbf56fe6..ef4d56a950 100644 --- a/test/Scoop-GetOpts.Tests.ps1 +++ b/test/Scoop-GetOpts.Tests.ps1 @@ -1,5 +1,7 @@ -. "$PSScriptRoot\Scoop-TestLib.ps1" -. "$PSScriptRoot\..\lib\getopt.ps1" +BeforeAll { + . "$PSScriptRoot\Scoop-TestLib.ps1" + . "$PSScriptRoot\..\lib\getopt.ps1" +} Describe 'getopt' -Tag 'Scoop' { It 'handle short option with required argument missing' { diff --git a/test/Scoop-Install.Tests.ps1 b/test/Scoop-Install.Tests.ps1 index 1e2c30d0a6..bafdfbe847 100644 --- a/test/Scoop-Install.Tests.ps1 +++ b/test/Scoop-Install.Tests.ps1 @@ -1,7 +1,9 @@ -. "$PSScriptRoot\Scoop-TestLib.ps1" -. "$PSScriptRoot\..\lib\core.ps1" -. "$PSScriptRoot\..\lib\manifest.ps1" -. "$PSScriptRoot\..\lib\install.ps1" +BeforeAll { + . "$PSScriptRoot\Scoop-TestLib.ps1" + . "$PSScriptRoot\..\lib\core.ps1" + . "$PSScriptRoot\..\lib\manifest.ps1" + . "$PSScriptRoot\..\lib\install.ps1" +} Describe 'appname_from_url' -Tag 'Scoop' { It 'should extract the correct name' { @@ -42,15 +44,17 @@ Describe 'is_in_dir' -Tag 'Scoop', 'Windows' { } Describe 'env add and remove path' -Tag 'Scoop', 'Windows' { - # test data - $manifest = @{ - 'env_add_path' = @('foo', 'bar') + BeforeAll { + # test data + $manifest = @{ + 'env_add_path' = @('foo', 'bar') + } + $testdir = Join-Path $PSScriptRoot 'path-test-directory' + $global = $false + + # store the original path to prevent leakage of tests + $origPath = $env:PATH } - $testdir = Join-Path $PSScriptRoot 'path-test-directory' - $global = $false - - # store the original path to prevent leakage of tests - $origPath = $env:PATH It 'should concat the correct path' { Mock add_first_in_path {} diff --git a/test/Scoop-Linting.Tests.ps1 b/test/Scoop-Linting.Tests.ps1 deleted file mode 100644 index 02cc2d93c2..0000000000 --- a/test/Scoop-Linting.Tests.ps1 +++ /dev/null @@ -1,41 +0,0 @@ -$repo_dir = (Get-Item $MyInvocation.MyCommand.Path).directory.parent.FullName - -Describe 'PSScriptAnalyzer' -Tag 'Linter' { - $scoop_modules = Get-ChildItem $repo_dir -Recurse -Include *.psd1, *.psm1, *.ps1 - $scoop_modules = $scoop_modules | Where-Object { $_.DirectoryName -notlike '*\supporting*' -and $_.DirectoryName -notlike '*\test*' } - $scoop_modules = $scoop_modules | Select-Object -ExpandProperty Directory -Unique - - Context 'Checking ScriptAnalyzer' { - It 'Invoke-ScriptAnalyzer Cmdlet should exist' { - { Get-Command Invoke-ScriptAnalyzer -ErrorAction Stop } | Should -Not -Throw - } - It 'PSScriptAnalyzerSettings.ps1 should exist' { - Test-Path "$repo_dir\PSScriptAnalyzerSettings.psd1" | Should -BeTrue - } - It 'There should be files to test' { - $scoop_modules.Count | Should -Not -Be 0 - } - } - - $linting_settings = Get-Item -Path "$repo_dir\PSScriptAnalyzerSettings.psd1" - - Context 'Linting all *.psd1, *.psm1 and *.ps1 files' { - foreach ($directory in $scoop_modules) { - $analysis = Invoke-ScriptAnalyzer -Path $directory.FullName -Settings $linting_settings.FullName - It "Should pass: $directory" { - $analysis.Count | Should -Be 0 - } - if ($analysis) { - foreach ($result in $analysis) { - switch -wildCard ($result.ScriptName) { - '*.psm1' { $type = 'Module' } - '*.ps1' { $type = 'Script' } - '*.psd1' { $type = 'Manifest' } - } - Write-Host -f Yellow " [*] $($result.Severity): $($result.Message)" - Write-Host -f Yellow " $($result.RuleName) in $type`: $directory\$($result.ScriptName):$($result.Line)" - } - } - } - } -} diff --git a/test/Scoop-Manifest.Tests.ps1 b/test/Scoop-Manifest.Tests.ps1 index 02a24162ab..232a946bbd 100644 --- a/test/Scoop-Manifest.Tests.ps1 +++ b/test/Scoop-Manifest.Tests.ps1 @@ -1,22 +1,28 @@ -. "$PSScriptRoot\Scoop-TestLib.ps1" -. "$PSScriptRoot\..\lib\json.ps1" -. "$PSScriptRoot\..\lib\manifest.ps1" +BeforeAll { + . "$PSScriptRoot\..\lib\json.ps1" + . "$PSScriptRoot\..\lib\manifest.ps1" +} -Describe 'Pretty json formating' -Tag 'Scoop' { - BeforeAll { - $format = "$PSScriptRoot\fixtures\format" - $manifests = Get-ChildItem "$format\formatted" -File -Filter '*.json' +Describe 'JSON parse and beautify' -Tag 'Scoop' { + Context 'Parse JSON' { + It 'success with valid json' { + { parse_json "$PSScriptRoot\fixtures\manifest\wget.json" } | Should -Not -Throw + } + It 'fails with invalid json' { + { parse_json "$PSScriptRoot\fixtures\manifest\broken_wget.json" } | Should -Throw + } } - - Context 'Beautify manifest' { - $manifests | ForEach-Object { - if ($PSVersionTable.PSVersion.Major -gt 5) { $_ = $_.Name } # Fix for pwsh - - It "$_" { - $pretty_json = (parse_json "$format\unformatted\$_") | ConvertToPrettyJson - $correct = (Get-Content "$format\formatted\$_") -join "`r`n" - $correct.CompareTo($pretty_json) | Should -Be 0 - } + Context 'Beautify JSON' { + BeforeDiscovery { + $manifests = (Get-ChildItem "$PSScriptRoot\fixtures\format\formatted" -File -Filter '*.json').Name + } + BeforeAll { + $format = "$PSScriptRoot\fixtures\format" + } + It '<_>' -ForEach $manifests { + $pretty_json = (parse_json "$format\unformatted\$_") | ConvertToPrettyJson + $correct = (Get-Content "$format\formatted\$_") -join "`r`n" + $correct.CompareTo($pretty_json) | Should -Be 0 } } } @@ -47,3 +53,34 @@ Describe 'Handle ARM64 and correctly fallback' -Tag 'Scoop' { Get-SupportedArchitecture $manifest3 'arm64' | Should -BeNullOrEmpty } } + +Describe 'Manifest Validator' -Tag 'Validator' { + # Could not use backslash '\' in Linux/macOS for .NET object 'Scoop.Validator' + BeforeAll { + Add-Type -Path "$PSScriptRoot\..\supporting\validator\bin\Scoop.Validator.dll" + $schema = "$PSScriptRoot/../schema.json" + } + + It 'Scoop.Validator is available' { + ([System.Management.Automation.PSTypeName]'Scoop.Validator').Type | Should -Be 'Scoop.Validator' + } + It 'fails with broken schema' { + $validator = New-Object Scoop.Validator("$PSScriptRoot/fixtures/manifest/broken_schema.json", $true) + $validator.Validate("$PSScriptRoot/fixtures/manifest/wget.json") | Should -BeFalse + $validator.Errors.Count | Should -Be 1 + $validator.Errors | Select-Object -First 1 | Should -Match 'broken_schema.*(line 6).*(position 4)' + } + It 'fails with broken manifest' { + $validator = New-Object Scoop.Validator($schema, $true) + $validator.Validate("$PSScriptRoot/fixtures/manifest/broken_wget.json") | Should -BeFalse + $validator.Errors.Count | Should -Be 1 + $validator.Errors | Select-Object -First 1 | Should -Match 'broken_wget.*(line 5).*(position 4)' + } + It 'fails with invalid manifest' { + $validator = New-Object Scoop.Validator($schema, $true) + $validator.Validate("$PSScriptRoot/fixtures/manifest/invalid_wget.json") | Should -BeFalse + $validator.Errors.Count | Should -Be 16 + $validator.Errors | Select-Object -First 1 | Should -Match "Property 'randomproperty' has not been defined and the schema does not allow additional properties\." + $validator.Errors | Select-Object -Last 1 | Should -Match 'Required properties are missing from object: version\.' + } +} diff --git a/test/Scoop-Versions.Tests.ps1 b/test/Scoop-Versions.Tests.ps1 index 5d653051bc..536f9cc7c3 100644 --- a/test/Scoop-Versions.Tests.ps1 +++ b/test/Scoop-Versions.Tests.ps1 @@ -1,5 +1,7 @@ -. "$PSScriptRoot\Scoop-TestLib.ps1" -. "$PSScriptRoot\..\lib\versions.ps1" +BeforeAll { + . "$PSScriptRoot\Scoop-TestLib.ps1" + . "$PSScriptRoot\..\lib\versions.ps1" +} Describe 'versions comparison' -Tag 'Scoop' { Context 'semver compliant versions' {